From b2e6379be832d92a0363291fe55c3f4670e2dde9 Mon Sep 17 00:00:00 2001 From: Philippe Normand Date: Tue, 24 Aug 2010 12:27:30 +0200 Subject: [PATCH] gstvalue: Add new GstInt64Range type new GstInt64Range to store gint64 ranges. API: GST_TYPE_INT64_RANGE API: gst_value_set_int64_range API: gst_value_get_int64_range_min API: gst_value_get_int64_range_max Fixes bug #627826. --- docs/gst/gstreamer-sections.txt | 8 + gst/gststructure.c | 7 + gst/gstvalue.c | 329 ++++++++++++++++++++++++++ gst/gstvalue.h | 25 ++ tests/check/gst/gstvalue.c | 509 +++++++++++++++++++++++++++++++++++++++- win32/common/libgstreamer.def | 4 + 6 files changed, 881 insertions(+), 1 deletion(-) diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index 39182f8..4488983 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -2636,6 +2636,13 @@ gst_value_set_int_range gst_value_get_int_range_min gst_value_get_int_range_max + +GST_VALUE_HOLDS_INT64_RANGE +GST_TYPE_INT64_RANGE +gst_value_set_int64_range +gst_value_get_int64_range_min +gst_value_get_int64_range_max + GST_VALUE_HOLDS_DOUBLE_RANGE GST_TYPE_DOUBLE_RANGE @@ -2742,6 +2749,7 @@ gst_fourcc_get_type gst_fraction_get_type gst_fraction_range_get_type gst_int_range_get_type +gst_int64_range_get_type gst_value_array_get_type gst_value_list_get_type diff --git a/gst/gststructure.c b/gst/gststructure.c index 39869d2..12fc954 100644 --- a/gst/gststructure.c +++ b/gst/gststructure.c @@ -1663,6 +1663,8 @@ gst_structure_value_get_generic_type (GValue * val) } } else if (G_VALUE_TYPE (val) == GST_TYPE_INT_RANGE) { return G_TYPE_INT; + } else if (G_VALUE_TYPE (val) == GST_TYPE_INT64_RANGE) { + return G_TYPE_INT64; } else if (G_VALUE_TYPE (val) == GST_TYPE_DOUBLE_RANGE) { return G_TYPE_DOUBLE; } else if (G_VALUE_TYPE (val) == GST_TYPE_FRACTION_RANGE) { @@ -1850,6 +1852,11 @@ gst_structure_parse_range (gchar * s, gchar ** after, GValue * value, 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)); + } 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)); } else if (G_VALUE_TYPE (&value1) == GST_TYPE_FRACTION) { range_type = GST_TYPE_FRACTION_RANGE; g_value_init (value, range_type); diff --git a/gst/gstvalue.c b/gst/gstvalue.c index a3c4393..2f0986a 100644 --- a/gst/gstvalue.c +++ b/gst/gstvalue.c @@ -193,6 +193,7 @@ gst_type_is_fixed (GType type) } /* our fundamental types that are certainly not fixed */ if (type == GST_TYPE_INT_RANGE || type == GST_TYPE_DOUBLE_RANGE || + type == GST_TYPE_INT64_RANGE || type == GST_TYPE_LIST || type == GST_TYPE_FRACTION_RANGE) { return FALSE; } @@ -900,6 +901,143 @@ gst_value_deserialize_int_range (GValue * dest, const gchar * s) return FALSE; } +/*************** + * int64 range * + ***************/ + +static void +gst_value_init_int64_range (GValue * value) +{ + value->data[0].v_int64 = 0; + value->data[1].v_int64 = 0; +} + +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; +} + +static gchar * +gst_value_collect_int64_range (GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + if (n_collect_values != 2) + return g_strdup_printf ("not enough value locations for `%s' passed", + G_VALUE_TYPE_NAME (value)); + if (collect_values[0].v_int64 >= collect_values[1].v_int64) + 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; + + return NULL; +} + +static gchar * +gst_value_lcopy_int64_range (const GValue * value, guint n_collect_values, + GTypeCValue * collect_values, guint collect_flags) +{ + guint64 *int_range_start = collect_values[0].v_pointer; + guint64 *int_range_end = collect_values[1].v_pointer; + + if (!int_range_start) + return g_strdup_printf ("start value location for `%s' passed as NULL", + G_VALUE_TYPE_NAME (value)); + if (!int_range_end) + return g_strdup_printf ("end 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; + + return NULL; +} + +/** + * gst_value_set_int64_range: + * @value: a GValue initialized to GST_TYPE_INT64_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_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_get_int64_range_min: + * @value: a GValue initialized to GST_TYPE_INT64_RANGE + * + * Gets the minimum of the range specified by @value. + * + * Returns: the minimum of the range + */ +gint64 +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; +} + +/** + * gst_value_get_int64_range_max: + * @value: a GValue initialized to GST_TYPE_INT64_RANGE + * + * Gets the maximum of the range specified by @value. + * + * Returns: the maxumum of the range + */ +gint64 +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; +} + +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); +} + +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) + 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); +} + +static gboolean +gst_value_deserialize_int64_range (GValue * dest, const gchar * s) +{ + g_warning ("unimplemented"); + return FALSE; +} + /**************** * double range * ****************/ @@ -2381,6 +2519,43 @@ gst_value_intersect_int_range_int_range (GValue * dest, const GValue * src1, } 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) { + gst_value_init_and_copy (dest, src1); + return TRUE; + } + + return FALSE; +} + +static gboolean +gst_value_intersect_int64_range_int64_range (GValue * dest, const GValue * src1, + const GValue * src2) +{ + gint64 min; + gint64 max; + + min = MAX (src1->data[0].v_int64, src2->data[0].v_int64); + max = MIN (src1->data[1].v_int64, src2->data[1].v_int64); + + if (min < max) { + g_value_init (dest, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (dest, min, max); + return TRUE; + } + if (min == max) { + g_value_init (dest, G_TYPE_INT64); + g_value_set_int64 (dest, min); + return TRUE; + } + + return FALSE; +} + +static gboolean gst_value_intersect_double_double_range (GValue * dest, const GValue * src1, const GValue * src2) { @@ -2674,6 +2849,123 @@ gst_value_subtract_int_range_int_range (GValue * dest, const GValue * minuend, } static gboolean +gst_value_subtract_int64_int64_range (GValue * dest, const GValue * minuend, + const GValue * subtrahend) +{ + gint64 min = gst_value_get_int64_range_min (subtrahend); + gint64 max = gst_value_get_int64_range_max (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) { + /* and the result is the int64 */ + gst_value_init_and_copy (dest, minuend); + return TRUE; + } + return FALSE; +} + +/* creates a new int64 range based on input values. + */ +static gboolean +gst_value_create_new_int64_range (GValue * dest, gint64 min1, gint64 max1, + gint64 min2, gint64 max2) +{ + GValue v1 = { 0, }; + GValue v2 = { 0, }; + GValue *pv1, *pv2; /* yeah, hungarian! */ + + if (min1 <= max1 && min2 <= max2) { + pv1 = &v1; + pv2 = &v2; + } else if (min1 <= max1) { + pv1 = dest; + pv2 = NULL; + } else if (min2 <= max2) { + pv1 = NULL; + pv2 = dest; + } else { + return FALSE; + } + + if (min1 < max1) { + g_value_init (pv1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (pv1, min1, max1); + } 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); + } else if (min2 == max2) { + g_value_init (pv2, G_TYPE_INT64); + g_value_set_int64 (pv2, min2); + } + + if (min1 <= max1 && min2 <= max2) { + gst_value_list_concat (dest, pv1, pv2); + g_value_unset (pv1); + g_value_unset (pv2); + } + return TRUE; +} + +static gboolean +gst_value_subtract_int64_range_int64 (GValue * dest, const GValue * minuend, + const GValue * subtrahend) +{ + gint64 min = gst_value_get_int64_range_min (minuend); + gint64 max = gst_value_get_int64_range_max (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) { + gst_value_init_and_copy (dest, minuend); + return TRUE; + } else { + /* max must be MAXINT64 too as val <= max */ + if (val == G_MAXINT64) { + max--; + val--; + } + /* min must be MININT64 too as val >= max */ + if (val == G_MININT64) { + min++; + val++; + } + gst_value_create_new_int64_range (dest, min, val - 1, val + 1, max); + } + return TRUE; +} + +static gboolean +gst_value_subtract_int64_range_int64_range (GValue * dest, + const GValue * minuend, const GValue * subtrahend) +{ + gint64 min1 = gst_value_get_int64_range_min (minuend); + gint64 max1 = gst_value_get_int64_range_max (minuend); + gint64 min2 = gst_value_get_int64_range_min (subtrahend); + gint64 max2 = gst_value_get_int64_range_max (subtrahend); + + if (max2 == G_MAXINT64 && min2 == G_MININT64) { + 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); + } else { + return gst_value_create_new_int64_range (dest, min1, MIN (min2 - 1, max1), + MAX (max2 + 1, min1), max1); + } +} + +static gboolean gst_value_subtract_double_double_range (GValue * dest, const GValue * minuend, const GValue * subtrahend) { @@ -4217,6 +4509,19 @@ static const GTypeValueTable _gst_int_range_value_table = { FUNC_VALUE_GET_TYPE (int_range, "GstIntRange"); +static const GTypeValueTable _gst_int64_range_value_table = { + gst_value_init_int64_range, + NULL, + gst_value_copy_int64_range, + NULL, + (char *) "qq", + gst_value_collect_int64_range, + (char *) "pp", + gst_value_lcopy_int64_range +}; + +FUNC_VALUE_GET_TYPE (int64_range, "GstInt64Range"); + static const GTypeValueTable _gst_double_range_value_table = { gst_value_init_double_range, NULL, @@ -4355,6 +4660,18 @@ _gst_value_initialize (void) { static GstValueTable gst_value = { 0, + gst_value_compare_int64_range, + gst_value_serialize_int64_range, + gst_value_deserialize_int64_range, + }; + + gst_value.type = gst_int64_range_get_type (); + gst_value_register (&gst_value); + } + + { + static GstValueTable gst_value = { + 0, gst_value_compare_double_range, gst_value_serialize_double_range, gst_value_deserialize_double_range, @@ -4501,6 +4818,8 @@ _gst_value_initialize (void) gst_value_transform_fourcc_string); g_value_register_transform_func (GST_TYPE_INT_RANGE, G_TYPE_STRING, gst_value_transform_int_range_string); + g_value_register_transform_func (GST_TYPE_INT64_RANGE, G_TYPE_STRING, + gst_value_transform_int64_range_string); g_value_register_transform_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_STRING, gst_value_transform_double_range_string); g_value_register_transform_func (GST_TYPE_FRACTION_RANGE, G_TYPE_STRING, @@ -4532,6 +4851,10 @@ _gst_value_initialize (void) gst_value_intersect_int_int_range); gst_value_register_intersect_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE, gst_value_intersect_int_range_int_range); + gst_value_register_intersect_func (G_TYPE_INT64, GST_TYPE_INT64_RANGE, + gst_value_intersect_int64_int64_range); + gst_value_register_intersect_func (GST_TYPE_INT64_RANGE, GST_TYPE_INT64_RANGE, + gst_value_intersect_int64_range_int64_range); gst_value_register_intersect_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE, gst_value_intersect_double_double_range); gst_value_register_intersect_func (GST_TYPE_DOUBLE_RANGE, @@ -4550,6 +4873,12 @@ _gst_value_initialize (void) gst_value_subtract_int_range_int); gst_value_register_subtract_func (GST_TYPE_INT_RANGE, GST_TYPE_INT_RANGE, gst_value_subtract_int_range_int_range); + gst_value_register_subtract_func (G_TYPE_INT64, GST_TYPE_INT64_RANGE, + gst_value_subtract_int64_int64_range); + gst_value_register_subtract_func (GST_TYPE_INT64_RANGE, G_TYPE_INT64, + gst_value_subtract_int64_range_int64); + gst_value_register_subtract_func (GST_TYPE_INT64_RANGE, GST_TYPE_INT64_RANGE, + gst_value_subtract_int64_range_int64_range); gst_value_register_subtract_func (G_TYPE_DOUBLE, GST_TYPE_DOUBLE_RANGE, gst_value_subtract_double_double_range); gst_value_register_subtract_func (GST_TYPE_DOUBLE_RANGE, G_TYPE_DOUBLE, diff --git a/gst/gstvalue.h b/gst/gstvalue.h index bc20873..8f918f4 100644 --- a/gst/gstvalue.h +++ b/gst/gstvalue.h @@ -102,6 +102,14 @@ G_BEGIN_DECLS #define GST_VALUE_HOLDS_INT_RANGE(x) (G_VALUE_HOLDS((x), gst_int_range_get_type ())) /** + * GST_VALUE_HOLDS_INT64_RANGE: + * @x: the #GValue to check + * + * Checks if the given #GValue contains a #GST_TYPE_INT64_RANGE value. + */ +#define GST_VALUE_HOLDS_INT64_RANGE(x) (G_VALUE_HOLDS((x), gst_int64_range_get_type ())) + +/** * GST_VALUE_HOLDS_DOUBLE_RANGE: * @x: the #GValue to check * @@ -204,6 +212,15 @@ G_BEGIN_DECLS #define GST_TYPE_INT_RANGE gst_int_range_get_type () /** + * GST_TYPE_INT64_RANGE: + * + * a #GValue type that represents an #gint64 range + * + * Returns: the #GType of GstInt64Range + */ +#define GST_TYPE_INT64_RANGE gst_int64_range_get_type () + +/** * GST_TYPE_DOUBLE_RANGE: * * a #GValue type that represents a floating point range with double precission @@ -416,6 +433,7 @@ struct _GstValueTable { }; GType gst_int_range_get_type (void); +GType gst_int64_range_get_type (void); GType gst_double_range_get_type (void); GType gst_fraction_range_get_type (void); GType gst_fourcc_get_type (void); @@ -469,6 +487,13 @@ void gst_value_set_int_range (GValue *value, gint gst_value_get_int_range_min (const GValue *value); gint gst_value_get_int_range_max (const GValue *value); +/* int64 range */ +void gst_value_set_int64_range (GValue *value, + gint64 start, + gint64 end); +gint64 gst_value_get_int64_range_min (const GValue *value); +gint64 gst_value_get_int64_range_max (const GValue *value); + /* double range */ void gst_value_set_double_range (GValue *value, gdouble start, diff --git a/tests/check/gst/gstvalue.c b/tests/check/gst/gstvalue.c index 86d11e5..a49bb14 100644 --- a/tests/check/gst/gstvalue.c +++ b/tests/check/gst/gstvalue.c @@ -1103,6 +1103,281 @@ GST_START_TEST (test_value_subtract_int) GST_END_TEST; +GST_START_TEST (test_value_subtract_int64) +{ + GValue dest = { 0 }; + GValue src1 = { 0 }; + GValue src2 = { 0 }; + const GValue *tmp; + gboolean ret; + + /* int64 <-> int64 + */ + g_value_init (&src1, G_TYPE_INT64); + g_value_set_int64 (&src1, 10); + g_value_init (&src2, G_TYPE_INT64); + g_value_set_int64 (&src2, 20); + /* subtract as in sets, result is 10 */ + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL); + g_value_unset (&dest); + + /* same values, yields empty set */ + ret = gst_value_subtract (&dest, &src1, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* int64 <-> int64_range + */ + + /* would yield an empty set */ + g_value_init (&src1, G_TYPE_INT64); + g_value_set_int64 (&src1, 10); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 0, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + + /* and the other way around, should create a list of two ranges. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int64_range_min (tmp) == 0); + fail_unless (gst_value_get_int64_range_max (tmp) == 9); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int64_range_min (tmp) == 11); + fail_unless (gst_value_get_int64_range_max (tmp) == 20); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* border case 1, empty set */ + g_value_init (&src1, G_TYPE_INT64); + g_value_set_int64 (&src1, 10); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 10, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + + /* and the other way around, should create a new range. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE); + fail_unless (gst_value_get_int64_range_min (&dest) == 11); + fail_unless (gst_value_get_int64_range_max (&dest) == 20); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* border case 2, empty set */ + g_value_init (&src1, G_TYPE_INT64); + g_value_set_int64 (&src1, 20); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 10, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + + /* and the other way around, should create a new range. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE); + fail_unless (gst_value_get_int64_range_min (&dest) == 10); + fail_unless (gst_value_get_int64_range_max (&dest) == 19); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* case 3, valid set */ + g_value_init (&src1, G_TYPE_INT64); + g_value_set_int64 (&src1, 0); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 10, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (G_VALUE_HOLDS_INT64 (&dest) == TRUE); + fail_unless (gst_value_compare (&dest, &src1) == GST_VALUE_EQUAL); + g_value_unset (&dest); + + /* and the other way around, should keep the range. */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE); + fail_unless (gst_value_get_int64_range_min (&dest) == 10); + fail_unless (gst_value_get_int64_range_max (&dest) == 20); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* int64_range <-> int64_range + */ + + /* same range, empty set */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 20); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 10, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* non overlapping ranges */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 20); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 30, 40); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE); + fail_unless (gst_value_get_int64_range_min (&dest) == 10); + fail_unless (gst_value_get_int64_range_max (&dest) == 20); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE); + fail_unless (gst_value_get_int64_range_min (&dest) == 30); + fail_unless (gst_value_get_int64_range_max (&dest) == 40); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* completely overlapping ranges */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 20); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 10, 30); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == FALSE); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE); + fail_unless (gst_value_get_int64_range_min (&dest) == 21); + fail_unless (gst_value_get_int64_range_max (&dest) == 30); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* partially overlapping ranges */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 20); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 15, 30); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE); + fail_unless (gst_value_get_int64_range_min (&dest) == 10); + fail_unless (gst_value_get_int64_range_max (&dest) == 14); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (&dest) == TRUE); + fail_unless (gst_value_get_int64_range_min (&dest) == 21); + fail_unless (gst_value_get_int64_range_max (&dest) == 30); + g_value_unset (&dest); + g_value_unset (&src1); + g_value_unset (&src2); + + /* create a hole { int64_range, int64_range } */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 30); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 15, 20); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int64_range_min (tmp) == 10); + fail_unless (gst_value_get_int64_range_max (tmp) == 14); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int64_range_min (tmp) == 21); + fail_unless (gst_value_get_int64_range_max (tmp) == 30); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* create a hole, { int64, int64 } */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 30); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 11, 29); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE); + fail_unless (g_value_get_int64 (tmp) == 10); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE); + fail_unless (g_value_get_int64 (tmp) == 30); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* create a hole, { int64, int64_range } */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 30); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 11, 28); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE); + fail_unless (g_value_get_int64 (tmp) == 10); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int64_range_min (tmp) == 29); + fail_unless (gst_value_get_int64_range_max (tmp) == 30); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); + + /* create a hole, { int64_range, int64 } */ + g_value_init (&src1, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src1, 10, 30); + g_value_init (&src2, GST_TYPE_INT64_RANGE); + gst_value_set_int64_range (&src2, 12, 29); + ret = gst_value_subtract (&dest, &src1, &src2); + fail_unless (ret == TRUE); + fail_unless (GST_VALUE_HOLDS_LIST (&dest) == TRUE); + tmp = gst_value_list_get_value (&dest, 0); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (tmp) == TRUE); + fail_unless (gst_value_get_int64_range_min (tmp) == 10); + fail_unless (gst_value_get_int64_range_max (tmp) == 11); + tmp = gst_value_list_get_value (&dest, 1); + fail_unless (G_VALUE_HOLDS_INT64 (tmp) == TRUE); + fail_unless (g_value_get_int64 (tmp) == 30); + g_value_unset (&dest); + /* the other way */ + ret = gst_value_subtract (&dest, &src2, &src1); + fail_unless (ret == FALSE); + g_value_unset (&src1); + g_value_unset (&src2); +} + +GST_END_TEST; + GST_START_TEST (test_value_subtract_double) { GValue dest = { 0 }; @@ -2043,7 +2318,234 @@ GST_START_TEST (test_serialize_deserialize_caps) GST_END_TEST; -static Suite * +GST_START_TEST (test_int_range) +{ + GValue range = { 0, }; + GValue start = { 0, }; + GValue end = { 0, }; + GValue src = { 0, }; + GValue dest = { 0, }; + GValue range2 = { 0, }; + + g_value_init (&range, GST_TYPE_INT_RANGE); + g_value_init (&range2, GST_TYPE_INT_RANGE); + g_value_init (&start, G_TYPE_INT); + g_value_init (&end, G_TYPE_INT); + g_value_init (&src, G_TYPE_INT); + + g_value_set_int (&src, 2); + + /* Check that a intersection of int & range = int */ + gst_value_set_int_range (&range, 1, 5); + + fail_unless (gst_value_intersect (&dest, &src, &range) == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == G_TYPE_INT); + fail_unless (gst_value_compare (&dest, &src) == GST_VALUE_EQUAL); + + /* Check that a intersection selects the overlapping range */ + gst_value_set_int_range (&range2, 2, 3); + g_value_unset (&dest); + fail_unless (gst_value_intersect (&dest, &range, &range2) == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT_RANGE); + + fail_unless (gst_value_compare (&dest, &range2) == GST_VALUE_EQUAL); + + /* Check that non intersection ranges don't intersect */ + gst_value_set_int_range (&range2, 6, 7); + g_value_unset (&dest); + fail_unless (gst_value_intersect (&dest, &range, &range2) == FALSE); + + g_value_unset (&start); + g_value_unset (&end); + g_value_unset (&range); + g_value_unset (&range2); + g_value_unset (&src); +} + +GST_END_TEST; + +GST_START_TEST (test_int64_range) +{ + GValue range = { 0, }; + GValue start = { 0, }; + GValue end = { 0, }; + GValue src = { 0, }; + GValue dest = { 0, }; + GValue range2 = { 0, }; + + g_value_init (&range, GST_TYPE_INT64_RANGE); + g_value_init (&range2, GST_TYPE_INT64_RANGE); + g_value_init (&start, G_TYPE_INT64); + g_value_init (&end, G_TYPE_INT64); + g_value_init (&src, G_TYPE_INT64); + + g_value_set_int64 (&src, 2); + + /* Check that a intersection of int64 & range = int64 */ + gst_value_set_int64_range (&range, 1, 5); + + fail_unless (gst_value_intersect (&dest, &src, &range) == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == G_TYPE_INT64); + fail_unless (gst_value_compare (&dest, &src) == GST_VALUE_EQUAL); + + /* Check that a intersection selects the overlapping range */ + gst_value_set_int64_range (&range2, 2, 3); + g_value_unset (&dest); + fail_unless (gst_value_intersect (&dest, &range, &range2) == TRUE); + fail_unless (G_VALUE_TYPE (&dest) == GST_TYPE_INT64_RANGE); + + fail_unless (gst_value_compare (&dest, &range2) == GST_VALUE_EQUAL); + + /* Check that non intersection ranges don't intersect */ + gst_value_set_int64_range (&range2, 6, 7); + g_value_unset (&dest); + fail_unless (gst_value_intersect (&dest, &range, &range2) == FALSE); + + g_value_unset (&start); + g_value_unset (&end); + g_value_unset (&range); + g_value_unset (&range2); + g_value_unset (&src); +} + +GST_END_TEST; + +GST_START_TEST (test_serialize_int64_range) +{ + int i = 0; + + gint64 int64_ranges[] = { + 0, 5, + 0, G_MAXINT, + 5, G_MAXINT32, + 5, G_MAXINT64, + }; + gint int64_ranges_size = sizeof (int64_ranges) / sizeof (int64_ranges[0]) / 2; + + gchar *int64_range_strings[] = { + g_strdup ("[ 0, 5 ]"), + g_strdup_printf ("[ 0, %" G_GINT64_FORMAT " ]", (gint64) G_MAXINT), + g_strdup_printf ("[ 5, %" G_GINT64_FORMAT " ]", (gint64) G_MAXINT32), + g_strdup_printf ("[ 5, %" G_GINT64_FORMAT " ]", G_MAXINT64), + }; + gint int64_range_strings_size = + sizeof (int64_range_strings) / sizeof (int64_range_strings[0]); + + fail_unless (int64_ranges_size == int64_range_strings_size); + + while (i < (int64_ranges_size * 2)) { + if ((i + 1) % 2) { + gchar *str; + gchar *str2; + GValue value = { 0 }; + const GValue *deserialized_value; + int idx = i / 2; + GstStructure *s; + + g_value_init (&value, GST_TYPE_INT64_RANGE); + + /* check serialization */ + gst_value_set_int64_range (&value, int64_ranges[i], int64_ranges[i + 1]); + str = gst_value_serialize (&value); + fail_unless (strcmp (str, int64_range_strings[idx]) == 0); + g_free (int64_range_strings[idx]); + + /* now deserialize again to an int64 range */ + s = gst_structure_new ("foo/bar", "range", GST_TYPE_INT64_RANGE, + int64_ranges[i], int64_ranges[i + 1], NULL); + deserialized_value = gst_structure_get_value (s, "range"); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (deserialized_value) == TRUE); + str2 = gst_value_serialize (deserialized_value); + + fail_unless (gst_value_get_int64_range_min (deserialized_value) == + int64_ranges[i]); + fail_unless (gst_value_get_int64_range_max (deserialized_value) == + int64_ranges[i + 1]); + + gst_structure_free (s); + g_free (str); + g_free (str2); + } + i++; + } +} + +GST_END_TEST; + +GST_START_TEST (test_deserialize_int_range) +{ + GstStructure *s; + gchar *str; + gchar *end = NULL; + const GValue *deserialized_value; + + /* check a valid int_range deserialization */ + str = g_strdup_printf ("foo/bar, range=[ 1, %d ];", G_MAXINT); + s = gst_structure_from_string (str, &end); + fail_unless (*end == '\0'); + deserialized_value = gst_structure_get_value (s, "range"); + fail_unless (GST_VALUE_HOLDS_INT_RANGE (deserialized_value) == TRUE); + fail_unless (gst_value_get_int_range_min (deserialized_value) == 1); + fail_unless (gst_value_get_int_range_max (deserialized_value) == G_MAXINT); + gst_structure_free (s); + end = NULL; + g_free (str); + + /* check invalid int_range deserialization */ + str = + g_strdup_printf ("foo/bar, range=[ 1, %" G_GINT64_FORMAT " ];", + (gint64) G_MAXINT + 1); + ASSERT_CRITICAL (s = gst_structure_from_string (str, &end)); + g_free (str); + str = + g_strdup_printf ("foo/bar, range=[ %" G_GINT64_FORMAT ", %" + G_GINT64_FORMAT " ];", (gint64) G_MAXINT, (gint64) G_MAXINT + 1); + ASSERT_CRITICAL (s = gst_structure_from_string (str, NULL)); + end = NULL; + g_free (str); + + /* check a valid int64_range deserialization. Those ranges need to + * be explicit about their storage type. */ + str = g_strdup_printf ("foo/bar, range=(gint64)[ 1, %d ];", G_MAXINT); + s = gst_structure_from_string (str, &end); + fail_unless (*end == '\0'); + deserialized_value = gst_structure_get_value (s, "range"); + fail_unless (GST_VALUE_HOLDS_INT64_RANGE (deserialized_value) == TRUE); + fail_unless (gst_value_get_int64_range_min (deserialized_value) == 1); + fail_unless (gst_value_get_int64_range_max (deserialized_value) == G_MAXINT); + fail_unless (strcmp (str, gst_structure_to_string (s)) == 0); + gst_structure_free (s); + end = NULL; + g_free (str); + + /* check invalid int64_range (starting with a gint) deserialization */ + str = + g_strdup_printf ("foo/bar, range=(gint64)[ 1, %" G_GUINT64_FORMAT " ];", + (guint64) G_MAXINT64 + 1); + ASSERT_CRITICAL (s = gst_structure_from_string (str, &end)); + fail_unless (*end == '\0'); + gst_structure_free (s); + end = NULL; + g_free (str); + + /* check invalid int64_range deserialization into a int64_range */ + str = + g_strdup_printf ("foo/bar, range=(gint64)[ %" G_GINT64_FORMAT ", %" + G_GUINT64_FORMAT " ];", (gint64) G_MAXINT, (guint64) G_MAXINT64 + 1); + ASSERT_CRITICAL (s = gst_structure_from_string (str, NULL)); + g_free (str); + + /* check invalid int64_range deserialization into a int_range */ + str = + g_strdup_printf ("foo/bar, range=[ %" G_GINT64_FORMAT ", %" + G_GUINT64_FORMAT " ];", (gint64) G_MAXINT, (guint64) G_MAXINT64 + 1); + s = gst_structure_from_string (str, &end); + fail_unless (s == NULL); + fail_unless (end == NULL); + g_free (str); +} + +GST_END_TEST static Suite * gst_value_suite (void) { Suite *s = suite_create ("GstValue"); @@ -2069,6 +2571,7 @@ gst_value_suite (void) tcase_add_test (tc_chain, test_value_compare); tcase_add_test (tc_chain, test_value_intersect); tcase_add_test (tc_chain, test_value_subtract_int); + tcase_add_test (tc_chain, test_value_subtract_int64); tcase_add_test (tc_chain, test_value_subtract_double); tcase_add_test (tc_chain, test_value_subtract_fraction); tcase_add_test (tc_chain, test_value_subtract_fraction_range); @@ -2077,6 +2580,10 @@ gst_value_suite (void) tcase_add_test (tc_chain, test_date_time); tcase_add_test (tc_chain, test_fraction_range); tcase_add_test (tc_chain, test_serialize_deserialize_caps); + tcase_add_test (tc_chain, test_int_range); + tcase_add_test (tc_chain, test_int64_range); + tcase_add_test (tc_chain, test_serialize_int64_range); + tcase_add_test (tc_chain, test_deserialize_int_range); return s; } diff --git a/win32/common/libgstreamer.def b/win32/common/libgstreamer.def index 902a437..a675505 100644 --- a/win32/common/libgstreamer.def +++ b/win32/common/libgstreamer.def @@ -464,6 +464,7 @@ EXPORTS gst_init gst_init_check gst_init_get_option_group + gst_int64_range_get_type gst_int_range_get_type gst_is_initialized gst_is_tag_list @@ -1131,6 +1132,8 @@ EXPORTS gst_value_get_fraction_numerator gst_value_get_fraction_range_max gst_value_get_fraction_range_min + gst_value_get_int64_range_max + gst_value_get_int64_range_min gst_value_get_int_range_max gst_value_get_int_range_min gst_value_get_mini_object @@ -1156,6 +1159,7 @@ EXPORTS gst_value_set_fraction gst_value_set_fraction_range gst_value_set_fraction_range_full + gst_value_set_int64_range gst_value_set_int_range gst_value_set_mini_object gst_value_set_structure -- 2.7.4