gst: utils: Add a multiply_int64 variant

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8262>
This commit is contained in:
Thibault Saunier 2025-01-08 15:01:32 -03:00 committed by GStreamer Marge Bot
parent c7a7eb1eb3
commit e77a16b2e6
3 changed files with 118 additions and 0 deletions

View file

@ -57598,6 +57598,41 @@ the result in @res_n and @res_d.</doc>
</parameter>
</parameters>
</function>
<function name="util_fraction_multiply_int64" c:identifier="gst_util_fraction_multiply_int64" version="1.26">
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstutils.c">Multiplies the fractions @a_n/@a_d and @b_n/@b_d and stores
the result in @res_n and @res_d.</doc>
<source-position filename="../subprojects/gstreamer/gst/gstutils.h"/>
<return-value transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstutils.c">%FALSE on overflow, %TRUE otherwise.</doc>
<type name="gboolean" c:type="gboolean"/>
</return-value>
<parameters>
<parameter name="a_n" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstutils.c">Numerator of first value</doc>
<type name="gint64" c:type="gint64"/>
</parameter>
<parameter name="a_d" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstutils.c">Denominator of first value</doc>
<type name="gint64" c:type="gint64"/>
</parameter>
<parameter name="b_n" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstutils.c">Numerator of second value</doc>
<type name="gint64" c:type="gint64"/>
</parameter>
<parameter name="b_d" transfer-ownership="none">
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstutils.c">Denominator of second value</doc>
<type name="gint64" c:type="gint64"/>
</parameter>
<parameter name="res_n" direction="out" caller-allocates="0" transfer-ownership="full">
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstutils.c">Pointer to #gint to hold the result numerator</doc>
<type name="gint64" c:type="gint64*"/>
</parameter>
<parameter name="res_d" direction="out" caller-allocates="0" transfer-ownership="full">
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstutils.c">Pointer to #gint to hold the result denominator</doc>
<type name="gint64" c:type="gint64*"/>
</parameter>
</parameters>
</function>
<function name="util_fraction_to_double" c:identifier="gst_util_fraction_to_double">
<doc xml:space="preserve" filename="../subprojects/gstreamer/gst/gstutils.c">Transforms a fraction to a #gdouble.</doc>
<source-position filename="../subprojects/gstreamer/gst/gstutils.h"/>

View file

@ -3926,6 +3926,86 @@ gst_util_fraction_multiply (gint a_n, gint a_d, gint b_n, gint b_d,
return TRUE;
}
/**
* gst_util_fraction_multiply_int64:
* @a_n: Numerator of first value
* @a_d: Denominator of first value
* @b_n: Numerator of second value
* @b_d: Denominator of second value
* @res_n: (out): Pointer to #gint to hold the result numerator
* @res_d: (out): Pointer to #gint to hold the result denominator
*
* Multiplies the fractions @a_n/@a_d and @b_n/@b_d and stores
* the result in @res_n and @res_d.
*
* Returns: %FALSE on overflow, %TRUE otherwise.
*
* Since: 1.26
*/
gboolean
gst_util_fraction_multiply_int64 (gint64 a_n, gint64 a_d, gint64 b_n,
gint64 b_d, gint64 * res_n, gint64 * res_d)
{
gint gcd;
gint64 initial_a_n, initial_a_d;
initial_a_n = a_n;
initial_a_d = a_d;
g_return_val_if_fail (res_n != NULL, FALSE);
g_return_val_if_fail (res_d != NULL, FALSE);
g_return_val_if_fail (a_d != 0, FALSE);
g_return_val_if_fail (b_d != 0, FALSE);
/* early out if either is 0, as its gcd would be 0 */
if (a_n == 0 || b_n == 0) {
*res_n = 0;
*res_d = 1;
return TRUE;
}
gcd = gst_util_greatest_common_divisor_int64 (a_n, a_d);
a_n /= gcd;
a_d /= gcd;
gcd = gst_util_greatest_common_divisor_int64 (b_n, b_d);
b_n /= gcd;
b_d /= gcd;
gcd = gst_util_greatest_common_divisor_int64 (a_n, b_d);
a_n /= gcd;
b_d /= gcd;
gcd = gst_util_greatest_common_divisor_int64 (a_d, b_n);
a_d /= gcd;
b_n /= gcd;
/* This would result in overflow */
if (a_n != 0 && G_MAXINT64 / ABS (a_n) < ABS (b_n)) {
gcd = gst_util_greatest_common_divisor_int64 (initial_a_n, initial_a_d);
GST_INFO ("gcd(a_n(%" G_GINT64_FORMAT "), a_d(%" G_GINT64_FORMAT ")) = %d",
initial_a_n, initial_a_d, gcd);
GST_INFO ("Integer overflow in numerator multiplication: %" G_GINT64_FORMAT
" * %" G_GINT64_FORMAT " > G_MAXINT64", ABS (a_n), ABS (b_n));
return FALSE;
}
if (G_MAXINT64 / ABS (a_d) < ABS (b_d)) {
GST_ERROR ("Integer overflow in denominator multiplication: %"
G_GINT64_FORMAT " * %" G_GINT64_FORMAT " > G_MAXINT64", ABS (a_d),
ABS (b_d));
return FALSE;
}
*res_n = a_n * b_n;
*res_d = a_d * b_d;
gcd = gst_util_greatest_common_divisor_int64 (*res_n, *res_d);
*res_n /= gcd;
*res_d /= gcd;
return TRUE;
}
/**
* gst_util_fraction_add:
* @a_n: Numerator of first value

View file

@ -1222,6 +1222,9 @@ GST_API
gboolean gst_util_fraction_multiply (gint a_n, gint a_d, gint b_n, gint b_d,
gint *res_n, gint *res_d);
GST_API
gboolean gst_util_fraction_multiply_int64 (gint64 a_n, gint64 a_d, gint64 b_n, gint64 b_d,
gint64 *res_n, gint64 *res_d);
GST_API
gboolean gst_util_fraction_add (gint a_n, gint a_d, gint b_n, gint b_d,
gint *res_n, gint *res_d);
GST_API