diff --git a/gst/audioresample/gstaudioresample.c b/gst/audioresample/gstaudioresample.c
index e7f5acc..c110f7a 100644
--- a/gst/audioresample/gstaudioresample.c
+++ b/gst/audioresample/gstaudioresample.c
@@ -235,9 +235,16 @@ gst_audio_resample_start (GstBaseTransform * base)
 {
   GstAudioResample *resample = GST_AUDIO_RESAMPLE (base);
 
-  resample->next_offset = -1;
-  resample->next_ts = -1;
-  resample->next_upstream_ts = -1;
+  resample->t0 = GST_CLOCK_TIME_NONE;
+  resample->in_offset0 = GST_BUFFER_OFFSET_NONE;
+  resample->out_offset0 = GST_BUFFER_OFFSET_NONE;
+  resample->next_in_offset = GST_BUFFER_OFFSET_NONE;
+  resample->next_out_offset = GST_BUFFER_OFFSET_NONE;
+
+  resample->tmp_in = NULL;
+  resample->tmp_in_size = 0;
+  resample->tmp_out = NULL;
+  resample->tmp_out_size = 0;
 
   return TRUE;
 }
@@ -754,112 +761,127 @@ gst_audio_resample_convert_buffer (GstAudioResample * resample,
   }
 }
 
+static guint8 *
+gst_audio_resample_workspace_realloc (guint8 ** workspace, guint * size,
+    guint new_size)
+{
+  guint8 *new;
+  if (new_size <= *size)
+    /* no need to resize */
+    return *workspace;
+  new = g_realloc (*workspace, new_size);
+  if (!new)
+    /* failure (re)allocating memeory */
+    return NULL;
+  /* success */
+  *workspace = new;
+  *size = new_size;
+  return *workspace;
+}
+
 static void
 gst_audio_resample_push_drain (GstAudioResample * resample)
 {
-  GstBuffer *buf;
-  GstBaseTransform *trans = GST_BASE_TRANSFORM (resample);
+  GstBuffer *outbuf;
   GstFlowReturn res;
   gint outsize;
   guint out_len, out_processed;
   gint err;
-  guint num, den, len;
-  guint8 *outtmp = NULL;
-  gboolean need_convert = FALSE;
+  guint num, den;
 
   if (!resample->state)
     return;
 
-  /* Don't drain samples if we were resetted. */
-  if (resample->next_ts == -1)
+  /* Don't drain samples if we were reset. */
+  if (!GST_CLOCK_TIME_IS_VALID (resample->t0))
     return;
 
-  need_convert = (resample->funcs->width != resample->width);
-
   resample->funcs->get_ratio (resample->state, &num, &den);
 
   out_len = resample->funcs->get_input_latency (resample->state);
   out_len = out_processed = (out_len * den + num - 1) / num;
-  outsize = (resample->width / 8) * out_len * resample->channels;
-
-  if (need_convert) {
-    guint outsize_tmp =
-        (resample->funcs->width / 8) * out_len * resample->channels;
-    if (outsize_tmp <= resample->tmp_out_size) {
-      outtmp = resample->tmp_out;
-    } else {
-      resample->tmp_out_size = outsize_tmp;
-      resample->tmp_out = outtmp = g_realloc (resample->tmp_out, outsize_tmp);
-    }
-  }
-
-  res =
-      gst_pad_alloc_buffer_and_set_caps (trans->srcpad, GST_BUFFER_OFFSET_NONE,
-      outsize, GST_PAD_CAPS (trans->srcpad), &buf);
+  outsize = out_len * resample->channels * (resample->width / 8);
 
+  res = gst_pad_alloc_buffer_and_set_caps (
+      GST_BASE_TRANSFORM_SRC_PAD (resample), GST_BUFFER_OFFSET_NONE, outsize,
+      GST_PAD_CAPS (GST_BASE_TRANSFORM_SRC_PAD (resample)), &outbuf);
   if (G_UNLIKELY (res != GST_FLOW_OK)) {
     GST_WARNING_OBJECT (resample, "failed allocating buffer of %d bytes",
         outsize);
     return;
   }
 
-  len = resample->funcs->get_input_latency (resample->state);
+  if (resample->funcs->width != resample->width) {
+    /* need to convert data format;  allocate workspace */
+    if (!gst_audio_resample_workspace_realloc (&resample->tmp_out,
+        &resample->tmp_out_size, (resample->funcs->width / 8) * out_len *
+	resample->channels)) {
+      GST_ERROR_OBJECT (resample, "failed to allocate workspace");
+      return;
+    }
 
-  err =
-      resample->funcs->process (resample->state,
-      NULL, &len, (need_convert) ? outtmp : GST_BUFFER_DATA (buf),
-      &out_processed);
+    /* process */
+    err = resample->funcs->process (resample->state, NULL, &out_len,
+        resample->tmp_out, &out_processed);
+
+    /* convert output format */
+    gst_audio_resample_convert_buffer (resample, resample->tmp_out,
+        GST_BUFFER_DATA (outbuf), out_processed, TRUE);
+  } else {
+    /* don't need to convert data format;  process */
+    err = resample->funcs->process (resample->state, NULL, &out_len,
+        GST_BUFFER_DATA (outbuf), &out_processed);
+  }
+
+  /* If we wrote more than allocated something is really wrong now
+   * and we should better abort immediately */
+  g_assert (out_len >= out_processed);
 
   if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
     GST_WARNING_OBJECT (resample, "Failed to process drain: %s",
         resample->funcs->strerror (err));
-    gst_buffer_unref (buf);
+    gst_buffer_unref (outbuf);
     return;
   }
 
   if (G_UNLIKELY (out_processed == 0)) {
     GST_WARNING_OBJECT (resample, "Failed to get drain, dropping buffer");
-    gst_buffer_unref (buf);
+    gst_buffer_unref (outbuf);
     return;
   }
 
-  /* If we wrote more than allocated something is really wrong now
-   * and we should better abort immediately */
-  g_assert (out_len >= out_processed);
-
-  if (need_convert)
-    gst_audio_resample_convert_buffer (resample, outtmp, GST_BUFFER_DATA (buf),
-        out_processed, TRUE);
-
-  GST_BUFFER_DURATION (buf) =
-      GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate);
-  GST_BUFFER_SIZE (buf) =
-      out_processed * resample->channels * (resample->width / 8);
-
-  if (GST_CLOCK_TIME_IS_VALID (resample->next_ts)) {
-    GST_BUFFER_TIMESTAMP (buf) = resample->next_ts;
-    resample->next_ts += GST_BUFFER_DURATION (buf);
-  }
-
-  if (resample->next_offset != -1) {
-    GST_BUFFER_OFFSET (buf) = resample->next_offset;
-    GST_BUFFER_OFFSET_END (buf) = resample->next_offset + out_processed;
-    resample->next_offset += out_processed;
+  if (GST_CLOCK_TIME_IS_VALID (resample->t0)) {
+    GST_BUFFER_OFFSET (outbuf) = resample->next_out_offset;
+    GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET (outbuf) +
+        out_processed;
+    GST_BUFFER_TIMESTAMP (outbuf) = resample->t0 +
+        gst_util_uint64_scale_int_round (GST_BUFFER_OFFSET (outbuf) -
+        resample->out_offset0, GST_SECOND, resample->outrate);
+    GST_BUFFER_DURATION (outbuf) = resample->t0 +
+        gst_util_uint64_scale_int_round (GST_BUFFER_OFFSET_END (outbuf) -
+        resample->out_offset0, GST_SECOND, resample->outrate) -
+        GST_BUFFER_TIMESTAMP (outbuf);
+    resample->next_out_offset += out_processed;
+    resample->next_in_offset += 0;
   } else {
-    /* should be impossible, but just incase */
-    GST_BUFFER_OFFSET (buf) = GST_BUFFER_OFFSET_NONE;
-    GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_OFFSET_NONE;
+    GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET_NONE;
+    GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_NONE;
+    GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
+    GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
   }
 
+  GST_BUFFER_SIZE (outbuf) =
+      out_processed * resample->channels * (resample->width / 8);
+
   GST_LOG_OBJECT (resample,
       "Pushing drain buffer of %u bytes with timestamp %" GST_TIME_FORMAT
       " duration %" GST_TIME_FORMAT " offset %" G_GUINT64_FORMAT " offset_end %"
-      G_GUINT64_FORMAT, GST_BUFFER_SIZE (buf),
-      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
-      GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf),
-      GST_BUFFER_OFFSET_END (buf));
+      G_GUINT64_FORMAT, GST_BUFFER_SIZE (outbuf),
+      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
+      GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf),
+      GST_BUFFER_OFFSET_END (outbuf));
 
-  res = gst_pad_push (trans->srcpad, buf);
+  res = gst_pad_push (GST_BASE_TRANSFORM_SRC_PAD (resample), outbuf);
 
   if (G_UNLIKELY (res != GST_FLOW_OK))
     GST_WARNING_OBJECT (resample, "Failed to push drain: %s",
@@ -876,16 +898,22 @@ gst_audio_resample_event (GstBaseTransform * base, GstEvent * event)
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_FLUSH_STOP:
       gst_audio_resample_reset_state (resample);
-      resample->next_offset = -1;
-      resample->next_ts = -1;
-      resample->next_upstream_ts = -1;
+      resample->t0 = GST_CLOCK_TIME_NONE;
+      resample->in_offset0 = GST_BUFFER_OFFSET_NONE;
+      resample->out_offset0 = GST_BUFFER_OFFSET_NONE;
+      resample->next_in_offset = GST_BUFFER_OFFSET_NONE;
+      resample->next_out_offset = GST_BUFFER_OFFSET_NONE;
+      resample->need_discont = TRUE;
       break;
     case GST_EVENT_NEWSEGMENT:
       gst_audio_resample_push_drain (resample);
       gst_audio_resample_reset_state (resample);
-      resample->next_offset = -1;
-      resample->next_ts = -1;
-      resample->next_upstream_ts = -1;
+      resample->t0 = GST_CLOCK_TIME_NONE;
+      resample->in_offset0 = GST_BUFFER_OFFSET_NONE;
+      resample->out_offset0 = GST_BUFFER_OFFSET_NONE;
+      resample->next_in_offset = GST_BUFFER_OFFSET_NONE;
+      resample->next_out_offset = GST_BUFFER_OFFSET_NONE;
+      resample->need_discont = TRUE;
       break;
     case GST_EVENT_EOS:
       gst_audio_resample_push_drain (resample);
@@ -900,26 +928,39 @@ gst_audio_resample_event (GstBaseTransform * base, GstEvent * event)
 
 static gboolean
 gst_audio_resample_check_discont (GstAudioResample * resample,
-    GstClockTime timestamp)
+    GstBuffer * buf)
 {
-  if (timestamp != GST_CLOCK_TIME_NONE &&
-      resample->next_upstream_ts != GST_CLOCK_TIME_NONE &&
-      timestamp != resample->next_upstream_ts) {
-    /* 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 - resample->next_upstream_ts;
-
-    if (ABS (diff) > (GST_SECOND + resample->inrate - 1) / resample->inrate) {
-      GST_WARNING_OBJECT (resample,
-          "encountered timestamp discontinuity of %s%" GST_TIME_FORMAT,
-          (diff < 0) ? "-" : "", GST_TIME_ARGS ((GstClockTime) ABS (diff)));
-      return TRUE;
-    }
-  }
+  guint64 offset;
+  guint64 delta;
+
+  /* is the incoming buffer a discontinuity? */
+  if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buf)))
+    return TRUE;
+
+  /* no valid timestamps or offsets to compare --> no discontinuity */
+  if (G_UNLIKELY (!(GST_BUFFER_TIMESTAMP_IS_VALID (buf) &&
+        GST_CLOCK_TIME_IS_VALID (resample->t0) &&
+	resample->in_offset0 != GST_BUFFER_OFFSET_NONE &&
+	resample->next_in_offset != GST_BUFFER_OFFSET_NONE)))
+    return FALSE;
 
-  return FALSE;
+  /* convert the inbound timestamp to an offset. */
+  offset = resample->in_offset0 + gst_util_uint64_scale_int_round (
+      GST_BUFFER_TIMESTAMP (buf) - resample->t0, resample->inrate,
+      GST_SECOND);
+
+  /* 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) */
+  delta = ABS ((gint64) (offset - resample->next_in_offset));
+  if (delta <= 1)
+    return FALSE;
+
+  GST_WARNING_OBJECT (resample,
+      "encountered timestamp discontinuity of %lu samples = %" GST_TIME_FORMAT,
+      delta, GST_TIME_ARGS (gst_util_uint64_scale_int_round (delta, GST_SECOND,
+      resample->inrate)));
+  return TRUE;
 }
 
 static GstFlowReturn
@@ -928,9 +969,7 @@ gst_audio_resample_process (GstAudioResample * resample, GstBuffer * inbuf,
 {
   guint32 in_len, in_processed;
   guint32 out_len, out_processed;
-  gint err = RESAMPLER_ERR_SUCCESS;
-  guint8 *in_tmp = NULL, *out_tmp = NULL;
-  gboolean need_convert = (resample->funcs->width != resample->width);
+  gint err;
 
   in_len = GST_BUFFER_SIZE (inbuf) / resample->channels;
   out_len = GST_BUFFER_SIZE (outbuf) / resample->channels;
@@ -941,95 +980,89 @@ gst_audio_resample_process (GstAudioResample * resample, GstBuffer * inbuf,
   in_processed = in_len;
   out_processed = out_len;
 
-  if (need_convert) {
-    guint in_size_tmp =
-        in_len * resample->channels * (resample->funcs->width / 8);
-    guint out_size_tmp =
-        out_len * resample->channels * (resample->funcs->width / 8);
-
-    if (in_size_tmp <= resample->tmp_in_size) {
-      in_tmp = resample->tmp_in;
-    } else {
-      resample->tmp_in = in_tmp = g_realloc (resample->tmp_in, in_size_tmp);
-      resample->tmp_in_size = in_size_tmp;
+  if (resample->funcs->width != resample->width) {
+    /* need to convert data format for processing;  ensure we have enough
+     * workspace available */
+    if (!gst_audio_resample_workspace_realloc (&resample->tmp_in,
+        &resample->tmp_in_size, in_len * resample->channels *
+        (resample->funcs->width / 8)) ||
+        !gst_audio_resample_workspace_realloc (&resample->tmp_out,
+        &resample->tmp_out_size, out_len * resample->channels *
+	(resample->funcs->width / 8))) {
+      GST_ERROR_OBJECT (resample, "failed to allocate workspace");
+      return GST_FLOW_ERROR;
     }
 
+    /* convert input */
     gst_audio_resample_convert_buffer (resample, GST_BUFFER_DATA (inbuf),
-        in_tmp, in_len, FALSE);
-
-    if (out_size_tmp <= resample->tmp_out_size) {
-      out_tmp = resample->tmp_out;
-    } else {
-      resample->tmp_out = out_tmp = g_realloc (resample->tmp_out, out_size_tmp);
-      resample->tmp_out_size = out_size_tmp;
-    }
-  }
+        resample->tmp_in, in_len, FALSE);
 
-  if (need_convert) {
+    /* process */
     err = resample->funcs->process (resample->state,
-        in_tmp, &in_processed, out_tmp, &out_processed);
+        resample->tmp_in, &in_processed, resample->tmp_out, &out_processed);
+
+    /* convert output */
+    gst_audio_resample_convert_buffer (resample, resample->tmp_out,
+        GST_BUFFER_DATA (outbuf), out_processed, TRUE);
   } else {
+    /* no format conversion required;  process */
     err = resample->funcs->process (resample->state,
-        (const guint8 *) GST_BUFFER_DATA (inbuf), &in_processed,
-        (guint8 *) GST_BUFFER_DATA (outbuf), &out_processed);
+        GST_BUFFER_DATA (inbuf), &in_processed,
+        GST_BUFFER_DATA (outbuf), &out_processed);
   }
 
-  if (G_UNLIKELY (in_len != in_processed))
-    GST_WARNING_OBJECT (resample, "Converted %d of %d input samples",
-        in_processed, in_len);
-
-  if (out_len != out_processed) {
-    if (out_processed == 0) {
-      GST_DEBUG_OBJECT (resample, "Converted to 0 samples, buffer dropped");
-
-      return GST_BASE_TRANSFORM_FLOW_DROPPED;
-    }
-
-    /* If we wrote more than allocated something is really wrong now
-     * and we should better abort immediately */
-    g_assert (out_len >= out_processed);
-  }
+  /* If we wrote more than allocated something is really wrong now and we
+   * should better abort immediately */
+  g_assert (out_len >= out_processed);
 
   if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
     GST_ERROR_OBJECT (resample, "Failed to convert data: %s",
         resample->funcs->strerror (err));
     return GST_FLOW_ERROR;
-  } else {
-
-    if (need_convert)
-      gst_audio_resample_convert_buffer (resample, out_tmp,
-          GST_BUFFER_DATA (outbuf), out_processed, TRUE);
-
-    GST_BUFFER_DURATION (outbuf) =
-        GST_FRAMES_TO_CLOCK_TIME (out_processed, resample->outrate);
-    GST_BUFFER_SIZE (outbuf) =
-        out_processed * resample->channels * (resample->width / 8);
+  }
 
-    if (GST_CLOCK_TIME_IS_VALID (resample->next_ts)) {
-      GST_BUFFER_TIMESTAMP (outbuf) = resample->next_ts;
-      resample->next_ts += GST_BUFFER_DURATION (outbuf);
-    }
+  if (G_UNLIKELY (in_len != in_processed)) {
+    GST_WARNING_OBJECT (resample, "converted %d of %d input samples",
+        in_processed, in_len);
+  }
 
-    if (resample->next_offset != -1) {
-      GST_BUFFER_OFFSET (outbuf) = resample->next_offset;
-      GST_BUFFER_OFFSET_END (outbuf) = resample->next_offset + out_processed;
-      resample->next_offset += out_processed;
-    } else {
-      /* should be impossible, but just incase */
-      GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET_NONE;
-      GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_NONE;
-    }
+  if (GST_CLOCK_TIME_IS_VALID (resample->t0)) {
+    GST_BUFFER_OFFSET (outbuf) = resample->next_out_offset;
+    GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET (outbuf) +
+        out_processed;
+    GST_BUFFER_TIMESTAMP (outbuf) = resample->t0 +
+        gst_util_uint64_scale_int_round (GST_BUFFER_OFFSET (outbuf) -
+        resample->out_offset0, GST_SECOND, resample->outrate);
+    GST_BUFFER_DURATION (outbuf) = resample->t0 +
+        gst_util_uint64_scale_int_round (GST_BUFFER_OFFSET_END (outbuf) -
+        resample->out_offset0, GST_SECOND, resample->outrate) -
+        GST_BUFFER_TIMESTAMP (outbuf);
+    resample->next_out_offset += out_processed;
+    resample->next_in_offset += in_len;
+  } else {
+    GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET_NONE;
+    GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_NONE;
+    GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE;
+    GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
+  }
 
-    GST_LOG_OBJECT (resample,
-        "Converted to buffer of %u bytes with timestamp %" GST_TIME_FORMAT
-        ", duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT
-        ", offset_end %" G_GUINT64_FORMAT, GST_BUFFER_SIZE (outbuf),
-        GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
-        GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
-        GST_BUFFER_OFFSET (outbuf), GST_BUFFER_OFFSET_END (outbuf));
+  GST_BUFFER_SIZE (outbuf) =
+      out_processed * resample->channels * (resample->width / 8);
 
-    return GST_FLOW_OK;
+  GST_LOG_OBJECT (resample,
+      "Converted to buffer of %" G_GUINT32_FORMAT
+      " samples (%u bytes) with timestamp %" GST_TIME_FORMAT", duration %"
+      GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT ", offset_end %"
+      G_GUINT64_FORMAT, out_processed, GST_BUFFER_SIZE (outbuf),
+      GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
+      GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
+      GST_BUFFER_OFFSET (outbuf), GST_BUFFER_OFFSET_END (outbuf));
+
+  if (out_processed == 0) {
+    GST_DEBUG_OBJECT (resample, "buffer dropped");
+    return GST_BASE_TRANSFORM_FLOW_DROPPED;
   }
+  return GST_FLOW_OK;
 }
 
 static GstFlowReturn
@@ -1038,8 +1071,6 @@ gst_audio_resample_transform (GstBaseTransform * base, GstBuffer * inbuf,
 {
   GstAudioResample *resample = GST_AUDIO_RESAMPLE (base);
   gulong size;
-  GstClockTime timestamp;
-  guint insamples;
   GstFlowReturn ret;
 
   if (resample->state == NULL) {
@@ -1054,50 +1085,43 @@ gst_audio_resample_transform (GstBaseTransform * base, GstBuffer * inbuf,
   }
 
   size = GST_BUFFER_SIZE (inbuf);
-  timestamp = GST_BUFFER_TIMESTAMP (inbuf);
 
   GST_LOG_OBJECT (resample, "transforming buffer of %ld bytes, ts %"
       GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT ", offset %"
       G_GINT64_FORMAT ", offset_end %" G_GINT64_FORMAT,
-      size, GST_TIME_ARGS (timestamp),
+      size, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)),
       GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf));
 
-  /* check for timestamp discontinuities and flush/reset if needed */
-  if (G_UNLIKELY (gst_audio_resample_check_discont (resample, timestamp)
-          || GST_BUFFER_IS_DISCONT (inbuf))) {
-    /* Flush internal samples */
+  /* check for timestamp discontinuities;  flush/reset if needed, and set
+   * flag to resync timestamp and offset counters and send event
+   * downstream */
+  if (G_UNLIKELY (gst_audio_resample_check_discont (resample, inbuf))) {
     gst_audio_resample_reset_state (resample);
-    /* Inform downstream element about discontinuity */
     resample->need_discont = TRUE;
-    /* We want to recalculate the timestamps */
-    resample->next_ts = -1;
-    resample->next_upstream_ts = -1;
-    resample->next_offset = -1;
-  }
-
-  insamples = GST_BUFFER_SIZE (inbuf) / resample->channels;
-  insamples /= (resample->width / 8);
-
-  if (GST_CLOCK_TIME_IS_VALID (timestamp)
-      && !GST_CLOCK_TIME_IS_VALID (resample->next_ts)) {
-    resample->next_ts = timestamp;
   }
 
-  if (resample->next_offset == -1) {
-    if (GST_BUFFER_OFFSET_IS_VALID (inbuf)) {
-      resample->next_offset =
-          gst_util_uint64_scale_int (GST_BUFFER_OFFSET (inbuf),
-          resample->outrate, resample->inrate);
-    } else if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
-      resample->next_offset =
-          GST_CLOCK_TIME_TO_FRAMES (timestamp, resample->outrate);
+  /* handle discontinuity */
+  if (G_UNLIKELY (resample->need_discont)) {
+    /* resync the timestamp and offset counters if possible */
+    if (GST_BUFFER_TIMESTAMP_IS_VALID (inbuf) &&
+        GST_BUFFER_OFFSET_IS_VALID (inbuf)) {
+      resample->t0 = GST_BUFFER_TIMESTAMP (inbuf);
+      resample->in_offset0 = GST_BUFFER_OFFSET (inbuf);
+      resample->out_offset0 = gst_util_uint64_scale_int_round (
+          resample->in_offset0, resample->outrate, resample->inrate);
+      resample->next_in_offset = resample->in_offset0;
+      resample->next_out_offset = resample->out_offset0;
     } else {
-      resample->next_offset = 0;
+      GST_DEBUG_OBJECT (resample, "found discontinuity but timestamp and/or " \
+      "offset is invalid, cannot sync output timestamp and offset counter");
+      resample->t0 = GST_CLOCK_TIME_NONE;
+      resample->in_offset0 = GST_BUFFER_OFFSET_NONE;
+      resample->out_offset0 = GST_BUFFER_OFFSET_NONE;
+      resample->next_in_offset = GST_BUFFER_OFFSET_NONE;
+      resample->next_out_offset = GST_BUFFER_OFFSET_NONE;
     }
-  }
-
-  if (G_UNLIKELY (resample->need_discont)) {
+    /* set DISCONT flag on output buffer */
     GST_DEBUG_OBJECT (resample, "marking this buffer with the DISCONT flag");
     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
     resample->need_discont = FALSE;
@@ -1107,13 +1131,15 @@ gst_audio_resample_transform (GstBaseTransform * base, GstBuffer * inbuf,
   if (G_UNLIKELY (ret != GST_FLOW_OK))
     return ret;
 
-  if (GST_CLOCK_TIME_IS_VALID (timestamp)
-      && !GST_CLOCK_TIME_IS_VALID (resample->next_upstream_ts))
-    resample->next_upstream_ts = timestamp;
-
-  if (GST_CLOCK_TIME_IS_VALID (resample->next_upstream_ts))
-    resample->next_upstream_ts +=
-        GST_FRAMES_TO_CLOCK_TIME (insamples, resample->inrate);
+  GST_DEBUG_OBJECT (resample, "input = samples [%" G_GUINT64_FORMAT ", %" \
+      G_GUINT64_FORMAT ") = [%" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT \
+      ") ns;  output = samples [%" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT \
+      ") = [%" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT ") ns",
+      GST_BUFFER_OFFSET(inbuf), GST_BUFFER_OFFSET_END(inbuf),
+      GST_BUFFER_TIMESTAMP(inbuf), GST_BUFFER_TIMESTAMP(inbuf) +
+      GST_BUFFER_DURATION(inbuf), GST_BUFFER_OFFSET(outbuf),
+      GST_BUFFER_OFFSET_END(outbuf), GST_BUFFER_TIMESTAMP(outbuf),
+      GST_BUFFER_TIMESTAMP(outbuf) + GST_BUFFER_DURATION(outbuf));
 
   return GST_FLOW_OK;
 }
@@ -1144,7 +1170,7 @@ gst_audio_resample_query (GstPad * pad, GstQuery * query)
       if (gst_base_transform_is_passthrough (trans))
         resampler_latency = 0;
 
-      if ((peer = gst_pad_get_peer (trans->sinkpad))) {
+      if ((peer = gst_pad_get_peer (GST_BASE_TRANSFORM_SINK_PAD (trans)))) {
         if ((res = gst_pad_query (peer, query))) {
           gst_query_parse_latency (query, &live, &min, &max);
 
@@ -1154,8 +1180,8 @@ gst_audio_resample_query (GstPad * pad, GstQuery * query)
 
           /* add our own latency */
           if (rate != 0 && resampler_latency != 0)
-            latency =
-                gst_util_uint64_scale (resampler_latency, GST_SECOND, rate);
+            latency = gst_util_uint64_scale_round (resampler_latency,
+                GST_SECOND, rate);
           else
             latency = 0;
 
@@ -1163,7 +1189,7 @@ gst_audio_resample_query (GstPad * pad, GstQuery * query)
               GST_TIME_ARGS (latency));
 
           min += latency;
-          if (max != GST_CLOCK_TIME_NONE)
+          if (GST_CLOCK_TIME_IS_VALID (max))
             max += latency;
 
           GST_DEBUG_OBJECT (resample, "Calculated total latency : min %"
diff --git a/gst/audioresample/gstaudioresample.h b/gst/audioresample/gstaudioresample.h
index fb6ef6c..2f41b2c 100644
--- a/gst/audioresample/gstaudioresample.h
+++ b/gst/audioresample/gstaudioresample.h
@@ -58,9 +58,11 @@ struct _GstAudioResample {
 
   gboolean need_discont;
 
-  guint64 next_offset;
-  GstClockTime next_ts;
-  GstClockTime next_upstream_ts;
+  GstClockTime t0;
+  guint64 in_offset0;
+  guint64 out_offset0;
+  guint64 next_in_offset;
+  guint64 next_out_offset;
   
   gint channels;
   gint inrate;
