From: <sl...@ke...> - 2010-08-28 07:32:41
|
Module: gstreamer Branch: master Commit: 8ca48752fb787ce708c86183b51505cd53d6b5ed URL: http://cgit.freedesktop.org/gstreamer/gstreamer/commit/?id=8ca48752fb787ce708c86183b51505cd53d6b5ed Author: Sebastian Dröge <seb...@co...> Date: Sat Aug 28 09:30:18 2010 +0200 utils: Add gst_util_fraction_compare() to compare fractions And use it for the fraction comparisons in gstvalue.c instead of using comparisons by first converting the fractions to double. Should fix bug #628174. API: gst_util_fraction_compare() --- gst/gstutils.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ gst/gstutils.h | 1 + gst/gstvalue.c | 43 +++++++++++++++++++++---------------------- 3 files changed, 70 insertions(+), 22 deletions(-) diff --git a/gst/gstutils.c b/gst/gstutils.c index f1b52af..265f427 100644 --- a/gst/gstutils.c +++ b/gst/gstutils.c @@ -4196,3 +4196,51 @@ gst_util_fraction_add (gint a_n, gint a_d, gint b_n, gint b_d, gint * res_n, return TRUE; } + +/** + * gst_util_fraction_compare: + * @a_n: Numerator of first value + * @a_d: Denominator of first value + * @b_n: Numerator of second value + * @b_d: Denominator of second value + * + * Compares the fractions @a_n/@a_d and @b_n/@b_d and returns + * -1 if a < b, 0 if a = b and 1 if a > b. + * + * Returns: -1 if a < b; 0 if a = b; 1 if a > b. + * + * Since: 0.10.31 + */ +gint +gst_util_fraction_compare (gint a_n, gint a_d, gint b_n, gint b_d) +{ + gint64 new_num_1; + gint64 new_num_2; + gint gcd; + + g_return_val_if_fail (a_d == 0 || b_d == 0, 0); + + /* Simplify */ + gcd = gst_util_greatest_common_divisor (a_n, a_d); + a_n /= gcd; + a_d /= gcd; + + gcd = gst_util_greatest_common_divisor (b_n, b_d); + b_n /= gcd; + b_d /= gcd; + + /* fractions are reduced when set, so we can quickly see if they're equal */ + if (a_n == b_n && a_d == b_d) + return 0; + + /* extend to 64 bits */ + new_num_1 = ((gint64) a_n) * b_d; + new_num_2 = ((gint64) b_n) * a_d; + if (new_num_1 < new_num_2) + return -1; + if (new_num_1 > new_num_2) + return 1; + + /* Should not happen because a_d and b_d are not 0 */ + g_return_val_if_reached (0); +} diff --git a/gst/gstutils.h b/gst/gstutils.h index 82860bb..f91b777 100644 --- a/gst/gstutils.h +++ b/gst/gstutils.h @@ -1172,6 +1172,7 @@ void gst_util_fraction_to_double (gint src_n, gint src_d, gdouble *dest); void gst_util_double_to_fraction (gdouble src, gint *dest_n, gint *dest_d); gboolean gst_util_fraction_multiply (gint a_n, gint a_d, gint b_n, gint b_d, gint *res_n, gint *res_d); gboolean gst_util_fraction_add (gint a_n, gint a_d, gint b_n, gint b_d, gint *res_n, gint *res_d); +gint gst_util_fraction_compare (gint a_n, gint a_d, gint b_n, gint b_d); /* sink message event diff --git a/gst/gstvalue.c b/gst/gstvalue.c index e6595ac..a3c4393 100644 --- a/gst/gstvalue.c +++ b/gst/gstvalue.c @@ -1106,10 +1106,9 @@ gst_value_collect_fraction_range (GValue * value, guint n_collect_values, if (collect_values[3].v_int == 0) return g_strdup_printf ("passed '0' as second denominator for `%s'", G_VALUE_TYPE_NAME (value)); - if ((((gdouble) collect_values[0].v_int) / - ((gdouble) collect_values[1].v_int)) >= - (((gdouble) collect_values[2].v_int) / - ((gdouble) collect_values[3].v_int))) + if (gst_util_fraction_compare (collect_values[0].v_int, + collect_values[1].v_int, collect_values[2].v_int, + collect_values[3].v_int) >= 0) return g_strdup_printf ("range start is not smaller than end for `%s'", G_VALUE_TYPE_NAME (value)); @@ -1175,9 +1174,8 @@ gst_value_set_fraction_range (GValue * value, const GValue * start, g_return_if_fail (GST_VALUE_HOLDS_FRACTION_RANGE (value)); g_return_if_fail (GST_VALUE_HOLDS_FRACTION (start)); g_return_if_fail (GST_VALUE_HOLDS_FRACTION (end)); - g_return_if_fail (((gdouble) start->data[0].v_int) / - ((gdouble) start->data[1].v_int) < - ((gdouble) end->data[0].v_int) / ((gdouble) end->data[1].v_int)); + g_return_if_fail (gst_util_fraction_compare (start->data[0].v_int, + start->data[1].v_int, end->data[0].v_int, end->data[1].v_int) < 0); vals = (GValue *) value->data[0].v_pointer; if (vals == NULL) { @@ -1210,9 +1208,8 @@ gst_value_set_fraction_range_full (GValue * value, g_return_if_fail (value != NULL); g_return_if_fail (denominator_start != 0); g_return_if_fail (denominator_end != 0); - g_return_if_fail (((gdouble) numerator_start) / - ((gdouble) denominator_start) < - ((gdouble) numerator_end) / ((gdouble) denominator_end)); + g_return_if_fail (gst_util_fraction_compare (numerator_start, + denominator_start, numerator_end, denominator_end) < 0); g_value_init (&start, GST_TYPE_FRACTION); g_value_init (&end, GST_TYPE_FRACTION); @@ -3910,9 +3907,7 @@ gst_value_compare_fraction (const GValue * value1, const GValue * value2) { gint n1, n2; gint d1, d2; - - gint64 new_num_1; - gint64 new_num_2; + gint ret; n1 = value1->data[0].v_int; n2 = value2->data[0].v_int; @@ -3923,18 +3918,22 @@ gst_value_compare_fraction (const GValue * value1, const GValue * value2) if (n1 == n2 && d1 == d2) return GST_VALUE_EQUAL; - /* extend to 64 bits */ - new_num_1 = ((gint64) n1) * d2; - new_num_2 = ((gint64) n2) * d1; - if (new_num_1 < new_num_2) + if (d1 == 0 && d2 == 0) + return GST_VALUE_UNORDERED; + else if (d1 == 0) + return GST_VALUE_GREATER_THAN; + else if (d2 == 0) return GST_VALUE_LESS_THAN; - if (new_num_1 > new_num_2) + + ret = gst_util_fraction_compare (n1, d1, n2, d2); + if (ret == -1) + return GST_VALUE_LESS_THAN; + else if (ret == 1) return GST_VALUE_GREATER_THAN; - /* new_num_1 == new_num_2 implies that both denominators must have - * been 0, beause otherwise simplification would have caught the - * equivalence */ - return GST_VALUE_UNORDERED; + /* Equality can't happen here because we check for that + * first already */ + g_return_val_if_reached (GST_VALUE_UNORDERED); } /********* |