diff --git a/gst/gstutils.c b/gst/gstutils.c
index 9e2344c..3f5141f 100644
--- a/gst/gstutils.c
+++ b/gst/gstutils.c
@@ -204,6 +204,14 @@ typedef union
   } l;
 } GstUInt64;
 
+/* used internally by muldiv functions to control rounding mode */
+typedef enum
+{
+  GST_ROUND_TONEAREST,
+  GST_ROUND_UP,
+  GST_ROUND_DOWN,
+} GstRoundingMode;
+
 /* multiply two 64-bit unsigned ints into a 128-bit unsigned int.  the high
  * and low 64 bits of the product are placed in c1 and c0 respectively.
  * this operation cannot overflow. */
@@ -343,13 +351,42 @@ gst_util_div96_32 (guint64 c1, guint64 c0, guint32 denom)
 
 static guint64
 gst_util_uint64_scale_uint64_unchecked (guint64 val, guint64 num,
-    guint64 denom)
+    guint64 denom, GstRoundingMode mode)
 {
   GstUInt64 c1, c0;
 
   /* compute 128-bit numerator product */
   gst_util_uint64_mul_uint64(&c1, &c0, val, num);
 
+  /* condition numerator based on rounding mode */
+  switch (mode) {
+  case GST_ROUND_TONEAREST:
+    /* add 1/2 the denominator to the numerator with carry */
+    if (G_MAXUINT64 - c0.ll < denom / 2) {
+      if (G_UNLIKELY (c1.ll == G_MAXUINT64))
+        /* overflow */
+        return G_MAXUINT64;
+      c1.ll++;
+    }
+    c0.ll += denom / 2;
+    break;
+
+  case GST_ROUND_UP:
+    /* add denominator - 1 to the numerator with carry */
+    if (G_MAXUINT64 - c0.ll < denom - 1) {
+      if (G_UNLIKELY (c1.ll == G_MAXUINT64))
+        /* overflow */
+        return G_MAXUINT64;
+      c1.ll++;
+    }
+    c0.ll += denom - 1;
+    break;
+
+  case GST_ROUND_DOWN:
+    /* natural behaviour */
+    break;
+  }
+
   /* high word as big as or bigger than denom --> overflow */
   if (G_UNLIKELY (c1.ll >= denom))
     return G_MAXUINT64;
@@ -360,13 +397,42 @@ gst_util_uint64_scale_uint64_unchecked (guint64 val, guint64 num,
 
 static inline guint64
 gst_util_uint64_scale_uint32_unchecked (guint64 val, guint32 num,
-    guint32 denom)
+    guint32 denom, GstRoundingMode mode)
 {
   GstUInt64 c1, c0;
 
   /* compute 96-bit numerator product */
   gst_util_uint64_mul_uint32 (&c1, &c0, val, num);
 
+  /* condition numerator based on rounding mode */
+  switch (mode) {
+  case GST_ROUND_TONEAREST:
+    /* add 1/2 the denominator to the numerator with carry */
+    if (G_MAXUINT64 - c0.ll < denom / 2) {
+      if (G_UNLIKELY (c1.ll == G_MAXUINT64))
+        /* overflow */
+        return G_MAXUINT64;
+      c1.ll++;
+    }
+    c0.ll += denom / 2;
+    break;
+
+  case GST_ROUND_UP:
+    /* add denominator - 1 to the numerator with carry */
+    if (G_MAXUINT64 - c0.ll < denom - 1) {
+      if (G_UNLIKELY (c1.ll == G_MAXUINT64))
+        /* overflow */
+        return G_MAXUINT64;
+      c1.ll++;
+    }
+    c0.ll += denom - 1;
+    break;
+
+  case GST_ROUND_DOWN:
+    /* natural behaviour */
+    break;
+  }
+
   /* high 32 bits as big as or bigger than denom --> overflow */
   if (G_UNLIKELY (c1.l.high >= denom))
     return G_MAXUINT64;
@@ -375,23 +441,10 @@ gst_util_uint64_scale_uint32_unchecked (guint64 val, guint32 num,
   return gst_util_div96_32 (c1.ll, c0.ll, denom);
 }
 
-/**
- * gst_util_uint64_scale:
- * @val: the number to scale
- * @num: the numerator of the scale ratio
- * @denom: the denominator of the scale ratio
- *
- * Scale @val by the rational number @num / @denom, avoiding overflows and
- * underflows and without loss of precision.
- *
- * This function can potentially be very slow if val and num are both
- * greater than G_MAXUINT32.
- *
- * Returns: @val * @num / @denom.  In the case of an overflow, this
- * function returns G_MAXUINT64.
- */
-guint64
-gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom)
+/* the guts of the gst_util_uint64_scale() variants */
+static guint64
+_gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom,
+    GstRoundingMode mode)
 {
   g_return_val_if_fail (denom != 0, G_MAXUINT64);
 
@@ -406,33 +459,97 @@ gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom)
     /* num is low --> use 96 bit muldiv */
     if (G_LIKELY (num <= G_MAXUINT32))
       return gst_util_uint64_scale_uint32_unchecked (val, (guint32) num,
-          (guint32) denom);
+          (guint32) denom, mode);
 
     /* num is high but val is low --> swap and use 96-bit muldiv */
     if (G_LIKELY (val <= G_MAXUINT32))
       return gst_util_uint64_scale_uint32_unchecked (num, (guint32) val,
-          (guint32) denom);
+          (guint32) denom, mode);
   }
 
   /* val is high and num is high --> use 128-bit muldiv */
-  return gst_util_uint64_scale_uint64_unchecked (val, num, denom);
+  return gst_util_uint64_scale_uint64_unchecked (val, num, denom, mode);
 }
 
 /**
- * gst_util_uint64_scale_int:
- * @val: guint64 (such as a #GstClockTime) to scale.
- * @num: numerator of the scale factor.
- * @denom: denominator of the scale factor.
+ * gst_util_uint64_scale:
+ * @val: the number to scale
+ * @num: the numerator of the scale ratio
+ * @denom: the denominator of the scale ratio
  *
  * Scale @val by the rational number @num / @denom, avoiding overflows and
- * underflows and without loss of precision.  @num must be non-negative and
- * @denom must be positive.
+ * underflows and without loss of precision.
+ *
+ * This function can potentially be very slow if val and num are both
+ * greater than G_MAXUINT32.
  *
  * Returns: @val * @num / @denom.  In the case of an overflow, this
- * function returns G_MAXUINT64.
+ * function returns G_MAXUINT64.  If the result is not exactly
+ * representable as an integer it is truncated.  See also
+ * gst_util_uint64_scale_round(), gst_util_uint64_scale_ceil(),
+ * gst_util_uint64_scale_int(), gst_util_uint64_scale_int_round(),
+ * gst_util_uint64_scale_int_ceil().
  */
 guint64
-gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
+gst_util_uint64_scale (guint64 val, guint64 num, guint64 denom)
+{
+  return _gst_util_uint64_scale (val, num, denom, GST_ROUND_DOWN);
+}
+
+/**
+ * gst_util_uint64_scale_round:
+ * @val: the number to scale
+ * @num: the numerator of the scale ratio
+ * @denom: the denominator of the scale ratio
+ *
+ * Scale @val by the rational number @num / @denom, avoiding overflows and
+ * underflows and without loss of precision.
+ *
+ * This function can potentially be very slow if val and num are both
+ * greater than G_MAXUINT32.
+ *
+ * Returns: @val * @num / @denom.  In the case of an overflow, this
+ * function returns G_MAXUINT64.  If the result is not exactly
+ * representable as an integer, it is rounded to the nearest integer
+ * (half-way cases are rounded up).  See also gst_util_uint64_scale(),
+ * gst_util_uint64_scale_ceil(), gst_util_uint64_scale_int(),
+ * gst_util_uint64_scale_int_round(), gst_util_uint64_scale_int_ceil().
+ */
+guint64
+gst_util_uint64_scale_round (guint64 val, guint64 num, guint64 denom)
+{
+  return _gst_util_uint64_scale (val, num, denom, GST_ROUND_TONEAREST);
+}
+
+/**
+ * gst_util_uint64_scale_ceil:
+ * @val: the number to scale
+ * @num: the numerator of the scale ratio
+ * @denom: the denominator of the scale ratio
+ *
+ * Scale @val by the rational number @num / @denom, avoiding overflows and
+ * underflows and without loss of precision.
+ *
+ * This function can potentially be very slow if val and num are both
+ * greater than G_MAXUINT32.
+ *
+ * Returns: @val * @num / @denom.  In the case of an overflow, this
+ * function returns G_MAXUINT64.  If the result is not exactly
+ * representable as an integer, it is rounded up.  See also
+ * gst_util_uint64_scale(), gst_util_uint64_scale_round(),
+ * gst_util_uint64_scale_int(), gst_util_uint64_scale_int_round(),
+ * gst_util_uint64_scale_int_ceil().
+ */
+guint64
+gst_util_uint64_scale_ceil (guint64 val, guint64 num, guint64 denom)
+{
+  return _gst_util_uint64_scale (val, num, denom, GST_ROUND_UP);
+}
+
+/* the guts of the gst_util_uint64_scale_int() variants */
+static guint64
+_gst_util_uint64_scale_int (guint64 val, gint num, gint denom,
+    GstRoundingMode mode)
 {
   g_return_val_if_fail (denom > 0, G_MAXUINT64);
   g_return_val_if_fail (num >= 0, G_MAXUINT64);
@@ -444,15 +561,101 @@ gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
     return val;
 
   if (val <= G_MAXUINT32) {
-    /* simple case, use two statements to prevent optimizer from screwing
-     * up result.  num and denom are not negative so casts are OK */
+    /* simple case.  num and denom are not negative so casts are OK.  when
+     * not truncating, the additions to the numerator cannot overflow
+     * because val*num <= G_MAXUINT32 * G_MAXINT32 < G_MAXUINT64 -
+     * G_MAXINT32, so there's room to add another gint32. */
     val *= (guint64) num;
+    switch (mode) {
+    case GST_ROUND_TONEAREST:
+      /* add 1/2 the denominator to the numerator. */
+      val += denom / 2;
+      break;
+
+    case GST_ROUND_UP:
+      /* add denominator - 1 to the numerator. */
+      val += denom - 1;
+      break;
+
+    case GST_ROUND_DOWN:
+      /* natural behaviour */
+      break;
+    }
     return val / (guint64) denom;
   }
 
   /* num and denom are not negative so casts are OK */
   return gst_util_uint64_scale_uint32_unchecked (val, (guint32) num,
-      (guint32) denom);
+      (guint32) denom, mode);
+}
+
+/**
+ * gst_util_uint64_scale_int:
+ * @val: guint64 (such as a #GstClockTime) to scale.
+ * @num: numerator of the scale factor.
+ * @denom: denominator of the scale factor.
+ *
+ * Scale @val by the rational number @num / @denom, avoiding overflows and
+ * underflows and without loss of precision.  @num must be non-negative and
+ * @denom must be positive.
+ *
+ * Returns: @val * @num / @denom.  In the case of an overflow, this
+ * function returns G_MAXUINT64.  If the result is not exactly
+ * representable as an integer, it is truncated.  See also
+ * gst_util_uint64_scale_int_round(), gst_util_uint64_scale_int_ceil(),
+ * gst_util_uint64_scale(), gst_util_uint64_scale_round(),
+ * gst_util_uint64_scale_ceil().
+ */
+guint64
+gst_util_uint64_scale_int (guint64 val, gint num, gint denom)
+{
+  return _gst_util_uint64_scale_int (val, num, denom, GST_ROUND_DOWN);
+}
+
+/**
+ * gst_util_uint64_scale_int_round:
+ * @val: guint64 (such as a #GstClockTime) to scale.
+ * @num: numerator of the scale factor.
+ * @denom: denominator of the scale factor.
+ *
+ * Scale @val by the rational number @num / @denom, avoiding overflows and
+ * underflows and without loss of precision.  @num must be non-negative and
+ * @denom must be positive.
+ *
+ * Returns: @val * @num / @denom.  In the case of an overflow, this
+ * function returns G_MAXUINT64.  If the result is not exactly
+ * representable as an integer, it is rounded to the nearest integer
+ * (half-way cases are rounded up).  See also gst_util_uint64_scale_int(),
+ * gst_util_uint64_scale_int_ceil(), gst_util_uint64_scale(),
+ * gst_util_uint64_scale_round(), gst_util_uint64_scale_ceil().
+ */
+guint64
+gst_util_uint64_scale_int_round (guint64 val, gint num, gint denom)
+{
+  return _gst_util_uint64_scale_int (val, num, denom, GST_ROUND_TONEAREST);
+}
+
+/**
+ * gst_util_uint64_scale_int_ceil:
+ * @val: guint64 (such as a #GstClockTime) to scale.
+ * @num: numerator of the scale factor.
+ * @denom: denominator of the scale factor.
+ *
+ * Scale @val by the rational number @num / @denom, avoiding overflows and
+ * underflows and without loss of precision.  @num must be non-negative and
+ * @denom must be positive.
+ *
+ * Returns: @val * @num / @denom.  In the case of an overflow, this
+ * function returns G_MAXUINT64.  If the result is not exactly
+ * representable as an integer, it is rounded up.  See also
+ * gst_util_uint64_scale_int(), gst_util_uint64_scale_int_round(),
+ * gst_util_uint64_scale(), gst_util_uint64_scale_round(),
+ * gst_util_uint64_scale_ceil().
+ */
+guint64
+gst_util_uint64_scale_int_ceil (guint64 val, gint num, gint denom)
+{
+  return _gst_util_uint64_scale_int (val, num, denom, GST_ROUND_UP);
 }
 
 /**
diff --git a/gst/gstutils.h b/gst/gstutils.h
index 6cac84b..0760183 100644
--- a/gst/gstutils.h
+++ b/gst/gstutils.h
@@ -64,8 +64,12 @@ gdouble         gst_util_guint64_to_gdouble     (guint64 value)  G_GNUC_PURE;
 #endif
 
 guint64		gst_util_uint64_scale		(guint64 val, guint64 num, guint64 denom) G_GNUC_PURE;
+guint64		gst_util_uint64_scale_round	(guint64 val, guint64 num, guint64 denom) G_GNUC_PURE;
+guint64		gst_util_uint64_scale_ceil	(guint64 val, guint64 num, guint64 denom) G_GNUC_PURE;
 
 guint64         gst_util_uint64_scale_int       (guint64 val, gint num, gint denom) G_GNUC_PURE;
+guint64         gst_util_uint64_scale_int_round (guint64 val, gint num, gint denom) G_GNUC_PURE;
+guint64         gst_util_uint64_scale_int_ceil  (guint64 val, gint num, gint denom) G_GNUC_PURE;
 
 guint32         gst_util_seqnum_next            (void);
 gint32          gst_util_seqnum_compare         (guint32 s1, guint32 s2);
