gst/audioresample/gstaudioresample.c: Don't trigger discontinuities for very small...
authorMichael Smith <msmith@xiph.org>
Thu, 15 Mar 2007 10:52:21 +0000 (10:52 +0000)
committerMichael Smith <msmith@xiph.org>
Thu, 15 Mar 2007 10:52:21 +0000 (10:52 +0000)
Original commit message from CVS:
* gst/audioresample/gstaudioresample.c:
(audioresample_check_discont), (audioresample_transform):
Don't trigger discontinuities for very small imperfections; a filter
flush will sound bad, and many plugins have rounding errors leading
to these.

ChangeLog
gst/audioresample/gstaudioresample.c

index 0d6c0bb..24f7c16 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2007-03-15  Michael Smith  <msmith@fluendo.com>
+
+       * gst/audioresample/gstaudioresample.c:
+       (audioresample_check_discont), (audioresample_transform):
+         Don't trigger discontinuities for very small imperfections; a filter
+         flush will sound bad, and many plugins have rounding errors leading
+         to these.
+
 2007-03-14 Philippe Kalaf <philippe.kalaf@collabora.co.uk>      
 
        * gst-libs/gst/rtp/gstbasertpaudiopayload.c:
index 8e9e768..98f08d8 100644 (file)
@@ -575,6 +575,33 @@ audioresample_do_output (GstAudioresample * audioresample, GstBuffer * outbuf)
   return GST_FLOW_OK;
 }
 
+/* llabs() is C99, so we might not have it; just use a simple macro... */
+#define LLABS(x) ((x>0)?x:-x)
+static gboolean
+audioresample_check_discont (GstAudioresample * audioresample,
+    GstClockTime timestamp)
+{
+  if (timestamp != GST_CLOCK_TIME_NONE &&
+      audioresample->prev_ts != GST_CLOCK_TIME_NONE &&
+      audioresample->prev_duration != GST_CLOCK_TIME_NONE &&
+      timestamp != audioresample->prev_ts + audioresample->prev_duration) {
+    /* Potentially a discontinuous buffer. However, it turns out that many
+     * elements generate imperfect streams due to rounding errors, so we permit
+     * a small error (up to one sample) without triggering a filter 
+     * flush/restart (if triggered incorrectly, this will be audible) */
+    GstClockTimeDiff diff = timestamp -
+        (audioresample->prev_ts + audioresample->prev_duration);
+
+    if (LLABS (diff) > GST_SECOND / audioresample->i_rate) {
+      GST_WARNING_OBJECT (audioresample,
+          "encountered timestamp discontinuity of %" G_GINT64_FORMAT, diff);
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
 static GstFlowReturn
 audioresample_transform (GstBaseTransform * base, GstBuffer * inbuf,
     GstBuffer * outbuf)
@@ -600,22 +627,13 @@ audioresample_transform (GstBaseTransform * base, GstBuffer * inbuf,
       GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf));
 
   /* check for timestamp discontinuities and flush/reset if needed */
-  if (GST_CLOCK_TIME_IS_VALID (audioresample->prev_ts) &&
-      GST_CLOCK_TIME_IS_VALID (audioresample->prev_duration)) {
-    GstClockTime ts_expected = audioresample->prev_ts +
-        audioresample->prev_duration;
-    GstClockTimeDiff ts_diff = GST_CLOCK_DIFF (ts_expected, timestamp);
-
-    if (G_UNLIKELY (ts_diff != 0)) {
-      GST_WARNING_OBJECT (audioresample,
-          "encountered timestamp discontinuity of %" G_GINT64_FORMAT, ts_diff);
-      /* Flush internal samples */
-      audioresample_pushthrough (audioresample);
-      /* Inform downstream element about discontinuity */
-      audioresample->need_discont = TRUE;
-      /* We want to recalculate the offset */
-      audioresample->ts_offset = -1;
-    }
+  if (G_UNLIKELY (audioresample_check_discont (audioresample, timestamp))) {
+    /* Flush internal samples */
+    audioresample_pushthrough (audioresample);
+    /* Inform downstream element about discontinuity */
+    audioresample->need_discont = TRUE;
+    /* We want to recalculate the offset */
+    audioresample->ts_offset = -1;
   }
 
   if (audioresample->ts_offset == -1) {