diff --git a/gst/audioresample/gstaudioresample.c b/gst/audioresample/gstaudioresample.c
index 6336db5..7c90520 100644
--- a/gst/audioresample/gstaudioresample.c
+++ b/gst/audioresample/gstaudioresample.c
@@ -63,7 +63,8 @@ enum
 {
   PROP_0,
   PROP_QUALITY,
-  PROP_FILTER_LENGTH
+  PROP_FILTER_LENGTH,
+  PROP_GAP_AWARE
 };
 
 #define SUPPORTED_CAPS \
@@ -193,6 +194,11 @@ gst_audio_resample_class_init (GstAudioResampleClass * klass)
       g_param_spec_int ("filter-length", "Filter length",
           "Length of the resample filter", 0, G_MAXINT, 64, G_PARAM_READWRITE));
 
+  g_object_class_install_property (gobject_class, PROP_GAP_AWARE,
+      g_param_spec_boolean ("gap-aware", "Gap Aware", "true = skip buffers " \
+          "flagged as gaps;  false = process all buffers", FALSE,
+          G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
   GST_BASE_TRANSFORM_CLASS (klass)->start =
       GST_DEBUG_FUNCPTR (gst_audio_resample_start);
   GST_BASE_TRANSFORM_CLASS (klass)->stop =
@@ -236,6 +242,8 @@ gst_audio_resample_start (GstBaseTransform * base)
 
   resample->need_discont = TRUE;
 
+  resample->count_gap = 0;
+  resample->count_nongap = 0;
   resample->t0 = GST_CLOCK_TIME_NONE;
   resample->in_offset0 = GST_BUFFER_OFFSET_NONE;
   resample->out_offset0 = GST_BUFFER_OFFSET_NONE;
@@ -385,8 +393,6 @@ gst_audio_resample_init_state (GstAudioResample * resample, gint width,
     return NULL;
   }
 
-  funcs->skip_zeros (ret);
-
   return ret;
 }
 
@@ -780,18 +786,46 @@ gst_audio_resample_workspace_realloc (guint8 ** workspace, guint * size,
   return *workspace;
 }
 
+/* Push history_len zeros into the filter, but discard the output. */
+static void
+gst_audio_resample_dump_drain (GstAudioResample * resample, guint history_len)
+{
+  gint outsize;
+  guint in_len, in_processed;
+  guint out_len, out_processed;
+  guint num, den;
+  void* buf;
+
+  g_assert(resample->state != NULL);
+
+  resample->funcs->get_ratio (resample->state, &num, &den);
+
+  in_len = in_processed = history_len;
+  out_processed = out_len = gst_util_uint64_scale_int_ceil (history_len, den, num);
+  outsize = out_len * resample->channels * (resample->funcs->width / 8);
+
+  if (out_len == 0)
+    return;
+
+  buf = g_malloc(outsize);
+  resample->funcs->process (resample->state, NULL, &in_processed, buf, &out_processed);
+  g_free(buf);
+
+  g_assert(in_len == in_processed);
+}
+
 static void
-gst_audio_resample_push_drain (GstAudioResample * resample)
+gst_audio_resample_push_drain (GstAudioResample * resample, guint history_len)
 {
   GstBuffer *outbuf;
   GstFlowReturn res;
   gint outsize;
-  guint history_len, out_len, out_processed;
+  guint in_len, in_processed;
+  guint out_len, out_processed;
   gint err;
   guint num, den;
 
-  if (!resample->state)
-    return;
+  g_assert (resample->state != NULL);
 
   /* Don't drain samples if we were reset. */
   if (!GST_CLOCK_TIME_IS_VALID (resample->t0))
@@ -799,11 +833,14 @@ gst_audio_resample_push_drain (GstAudioResample * resample)
 
   resample->funcs->get_ratio (resample->state, &num, &den);
 
-  history_len = resample->funcs->get_input_latency (resample->state);
+  in_len = in_processed = history_len;
   out_len = out_processed =
       gst_util_uint64_scale_int_ceil (history_len, den, num);
   outsize = out_len * resample->channels * (resample->width / 8);
 
+  if (out_len == 0)
+    return;
+
   res =
       gst_pad_alloc_buffer_and_set_caps (GST_BASE_TRANSFORM_SRC_PAD (resample),
       GST_BUFFER_OFFSET_NONE, outsize,
@@ -824,7 +861,7 @@ gst_audio_resample_push_drain (GstAudioResample * resample)
     }
 
     /* process */
-    err = resample->funcs->process (resample->state, NULL, &history_len,
+    err = resample->funcs->process (resample->state, NULL, &in_processed,
         resample->tmp_out, &out_processed);
 
     /* convert output format */
@@ -832,7 +869,7 @@ gst_audio_resample_push_drain (GstAudioResample * resample)
         GST_BUFFER_DATA (outbuf), out_processed, TRUE);
   } else {
     /* don't need to convert data format;  process */
-    err = resample->funcs->process (resample->state, NULL, &history_len,
+    err = resample->funcs->process (resample->state, NULL, &in_processed,
         GST_BUFFER_DATA (outbuf), &out_processed);
   }
 
@@ -847,12 +884,6 @@ gst_audio_resample_push_drain (GstAudioResample * resample)
     return;
   }
 
-  if (G_UNLIKELY (out_processed == 0)) {
-    GST_WARNING_OBJECT (resample, "Failed to get drain, dropping buffer");
-    gst_buffer_unref (outbuf);
-    return;
-  }
-
   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;
@@ -864,7 +895,7 @@ gst_audio_resample_push_drain (GstAudioResample * resample)
         resample->out_offset0, GST_SECOND, resample->outrate) -
         GST_BUFFER_TIMESTAMP (outbuf);
     resample->next_out_offset += out_processed;
-    resample->next_in_offset += 0;
+    resample->next_in_offset += history_len;
   } else {
     GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET_NONE;
     GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_NONE;
@@ -872,6 +903,12 @@ gst_audio_resample_push_drain (GstAudioResample * resample)
     GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE;
   }
 
+  if (G_UNLIKELY (out_processed == 0 && in_len * den > num)) {
+    GST_WARNING_OBJECT (resample, "Failed to get drain, dropping buffer");
+    gst_buffer_unref (outbuf);
+    return;
+  }
+
   GST_BUFFER_SIZE (outbuf) =
       out_processed * resample->channels * (resample->width / 8);
 
@@ -900,6 +937,11 @@ gst_audio_resample_event (GstBaseTransform * base, GstEvent * event)
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_FLUSH_STOP:
       gst_audio_resample_reset_state (resample);
+      if (resample->state)
+        resample->count_gap = resample->funcs->get_filt_len (resample->state);
+      else
+        resample->count_gap = 0;
+      resample->count_nongap = 0;
       resample->t0 = GST_CLOCK_TIME_NONE;
       resample->in_offset0 = GST_BUFFER_OFFSET_NONE;
       resample->out_offset0 = GST_BUFFER_OFFSET_NONE;
@@ -908,8 +950,14 @@ gst_audio_resample_event (GstBaseTransform * base, GstEvent * event)
       resample->need_discont = TRUE;
       break;
     case GST_EVENT_NEWSEGMENT:
-      gst_audio_resample_push_drain (resample);
+      if (resample->state)
+        gst_audio_resample_push_drain (resample, resample->count_nongap);
       gst_audio_resample_reset_state (resample);
+      if (resample->state)
+        resample->count_gap = resample->funcs->get_filt_len (resample->state);
+      else
+        resample->count_gap = 0;
+      resample->count_nongap = 0;
       resample->t0 = GST_CLOCK_TIME_NONE;
       resample->in_offset0 = GST_BUFFER_OFFSET_NONE;
       resample->out_offset0 = GST_BUFFER_OFFSET_NONE;
@@ -918,7 +966,8 @@ gst_audio_resample_event (GstBaseTransform * base, GstEvent * event)
       resample->need_discont = TRUE;
       break;
     case GST_EVENT_EOS:
-      gst_audio_resample_push_drain (resample);
+      if (resample->state)
+        gst_audio_resample_push_drain (resample, resample->count_nongap);
       gst_audio_resample_reset_state (resample);
       break;
     default:
@@ -933,6 +982,8 @@ gst_audio_resample_check_discont (GstAudioResample * resample, GstBuffer * buf)
 {
   guint64 offset;
   guint64 delta;
+  guint filt_len = resample->funcs->get_filt_len (resample->state);
+  guint64 delay = gst_util_uint64_scale_round (filt_len, GST_SECOND, 2 * resample->inrate);
 
   /* is the incoming buffer a discontinuity? */
   if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buf)))
@@ -949,7 +1000,7 @@ gst_audio_resample_check_discont (GstAudioResample * resample, GstBuffer * buf)
   offset =
       resample->in_offset0 +
       gst_util_uint64_scale_int_round (GST_BUFFER_TIMESTAMP (buf) -
-      resample->t0, resample->inrate, GST_SECOND);
+      resample->t0 - delay, 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
@@ -972,7 +1023,7 @@ gst_audio_resample_process (GstAudioResample * resample, GstBuffer * inbuf,
 {
   guint32 in_len, in_processed;
   guint32 out_len, out_processed;
-  gint err;
+  guint filt_len = resample->funcs->get_filt_len (resample->state);
 
   in_len = GST_BUFFER_SIZE (inbuf) / resample->channels;
   out_len = GST_BUFFER_SIZE (outbuf) / resample->channels;
@@ -983,47 +1034,91 @@ gst_audio_resample_process (GstAudioResample * resample, GstBuffer * inbuf,
   in_processed = in_len;
   out_processed = out_len;
 
-  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;
+  if (GST_BUFFER_FLAG_IS_SET (inbuf, GST_BUFFER_FLAG_GAP)) {
+    resample->count_nongap = 0;
+    if (resample->count_gap < filt_len) {
+      guint zeros_to_push;
+      if (in_len >= filt_len - resample->count_gap)
+        zeros_to_push = filt_len - resample->count_gap;
+      else
+        zeros_to_push = in_len;
+
+      gst_audio_resample_push_drain (resample, zeros_to_push);
+      in_len -= zeros_to_push;
+      resample->count_gap += zeros_to_push;
     }
 
-    /* convert input */
-    gst_audio_resample_convert_buffer (resample, GST_BUFFER_DATA (inbuf),
-        resample->tmp_in, in_len, FALSE);
+    {
+      guint num, den;
+      resample->funcs->get_ratio (resample->state, &num, &den);
+      out_processed = gst_util_uint64_scale_int_ceil (resample->next_in_offset - resample->in_offset0 + in_len, den, num) - resample->next_out_offset + resample->out_offset0;
+
+      memset (GST_BUFFER_DATA (outbuf), 0, GST_BUFFER_SIZE (outbuf));
+      if (resample->gap_aware)
+        GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
+      resample->count_gap += in_len;
+      in_processed = in_len;
+    }
+  } else /* not a gap */ {
+    gint err;
 
-    /* process */
-    err = resample->funcs->process (resample->state,
-        resample->tmp_in, &in_processed, resample->tmp_out, &out_processed);
+    if (resample->count_gap > filt_len)
+    {
+      /* push in enough zeros to restore the filter to the right offset */
+      guint num, den;
+      resample->funcs->get_ratio (resample->state, &num, &den);
+      gst_audio_resample_dump_drain (resample, (resample->count_gap - filt_len) % num);
+    }
+    resample->count_gap = 0;
+    if (resample->count_nongap < filt_len)
+    {
+      resample->count_nongap += in_len;
+      if (resample->count_nongap > filt_len)
+        resample->count_nongap = filt_len;
+    }
 
-    /* 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,
-        GST_BUFFER_DATA (inbuf), &in_processed,
-        GST_BUFFER_DATA (outbuf), &out_processed);
+    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),
+          resample->tmp_in, in_len, FALSE);
+
+      /* process */
+      err = resample->funcs->process (resample->state,
+          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,
+          GST_BUFFER_DATA (inbuf), &in_processed,
+          GST_BUFFER_DATA (outbuf), &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;
+    }
   }
 
   /* 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;
-  }
-
   if (G_UNLIKELY (in_len != in_processed)) {
     GST_WARNING_OBJECT (resample, "converted %d of %d input samples",
         in_processed, in_len);
@@ -1108,7 +1203,10 @@ gst_audio_resample_transform (GstBaseTransform * base, GstBuffer * inbuf,
     /* 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);
+      guint filt_len = resample->funcs->get_filt_len (resample->state);
+      guint64 delay = gst_util_uint64_scale_round (filt_len, GST_SECOND, 2 * resample->inrate);
+      resample->count_gap = resample->funcs->get_filt_len (resample->state);
+      resample->t0 = GST_BUFFER_TIMESTAMP (inbuf) - delay;
       resample->in_offset0 = GST_BUFFER_OFFSET (inbuf);
       resample->out_offset0 =
           gst_util_uint64_scale_int_round (resample->in_offset0,
@@ -1278,6 +1376,15 @@ gst_audio_resample_set_property (GObject * object, guint prop_id,
       GST_BASE_TRANSFORM_UNLOCK (resample);
       break;
     }
+    case PROP_GAP_AWARE:
+      GST_BASE_TRANSFORM_LOCK (resample);
+      /* FIXME:  too bad we need to record our own copy of this, why
+       * doesn't basetransform expose its flag? */
+      resample->gap_aware = g_value_get_boolean (value);
+      gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (resample),
+          resample->gap_aware);
+      GST_BASE_TRANSFORM_UNLOCK (resample);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1333,6 +1440,9 @@ gst_audio_resample_get_property (GObject * object, guint prop_id,
           break;
       }
       break;
+    case PROP_GAP_AWARE:
+      g_value_set_boolean (value, resample->gap_aware);
+      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
diff --git a/gst/audioresample/gstaudioresample.h b/gst/audioresample/gstaudioresample.h
index 2f41b2c..05e233b 100644
--- a/gst/audioresample/gstaudioresample.h
+++ b/gst/audioresample/gstaudioresample.h
@@ -64,6 +64,10 @@ struct _GstAudioResample {
   guint64 next_in_offset;
   guint64 next_out_offset;
   
+  gboolean gap_aware;
+  guint count_gap;
+  guint count_nongap;
+
   gint channels;
   gint inrate;
   gint outrate;
diff --git a/gst/audioresample/resample.c b/gst/audioresample/resample.c
index 2cfd544..7d42f0e 100644
--- a/gst/audioresample/resample.c
+++ b/gst/audioresample/resample.c
@@ -1311,6 +1311,12 @@ speex_resampler_get_output_latency (SpeexResamplerState * st)
 }
 
 EXPORT int
+speex_resampler_get_filt_len (SpeexResamplerState * st)
+{
+  return st->filt_len;
+}
+
+EXPORT int
 speex_resampler_skip_zeros (SpeexResamplerState * st)
 {
   spx_uint32_t i;
diff --git a/gst/audioresample/speex_resampler.h b/gst/audioresample/speex_resampler.h
index 9dc0280..894b380 100644
--- a/gst/audioresample/speex_resampler.h
+++ b/gst/audioresample/speex_resampler.h
@@ -73,6 +73,7 @@
 #define speex_resampler_get_output_stride CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_stride)
 #define speex_resampler_get_input_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_input_latency)
 #define speex_resampler_get_output_latency CAT_PREFIX(RANDOM_PREFIX,_resampler_get_output_latency)
+#define speex_resampler_get_filt_len CAT_PREFIX(RANDOM_PREFIX,_resampler_get_filt_len)
 #define speex_resampler_skip_zeros CAT_PREFIX(RANDOM_PREFIX,_resampler_skip_zeros)
 #define speex_resampler_reset_mem CAT_PREFIX(RANDOM_PREFIX,_resampler_reset_mem)
 #define speex_resampler_strerror CAT_PREFIX(RANDOM_PREFIX,_resampler_strerror)
@@ -333,6 +334,11 @@ int speex_resampler_get_input_latency(SpeexResamplerState *st);
  */
 int speex_resampler_get_output_latency(SpeexResamplerState *st);
 
+/** Get the length of the filter in input samples.
+ * @param st Resampler state
+ */
+int speex_resampler_get_filt_len(SpeexResamplerState *st);
+
 /** Make sure that the first samples to go out of the resamplers don't have 
  * leading zeros. This is only useful before starting to use a newly created 
  * resampler. It is recommended to use that when resampling an audio file, as
diff --git a/gst/audioresample/speex_resampler_wrapper.h b/gst/audioresample/speex_resampler_wrapper.h
index 36d444f..08a82bc 100644
--- a/gst/audioresample/speex_resampler_wrapper.h
+++ b/gst/audioresample/speex_resampler_wrapper.h
@@ -52,6 +52,7 @@ typedef struct {
   void (*get_ratio) (SpeexResamplerState * st,
     guint32 * ratio_num, guint32 * ratio_den);
   int (*get_input_latency) (SpeexResamplerState * st);
+  int (*get_filt_len) (SpeexResamplerState * st);
   int (*set_quality) (SpeexResamplerState * st, gint quality);
   int (*reset_mem) (SpeexResamplerState * st);
   int (*skip_zeros) (SpeexResamplerState * st);
@@ -71,6 +72,7 @@ void resample_float_resampler_get_rate (SpeexResamplerState * st,
 void resample_float_resampler_get_ratio (SpeexResamplerState * st,
     guint32 * ratio_num, guint32 * ratio_den);
 int resample_float_resampler_get_input_latency (SpeexResamplerState * st);
+int resample_float_resampler_get_filt_len (SpeexResamplerState * st);
 int resample_float_resampler_set_quality (SpeexResamplerState * st, gint quality);
 int resample_float_resampler_reset_mem (SpeexResamplerState * st);
 int resample_float_resampler_skip_zeros (SpeexResamplerState * st);
@@ -85,6 +87,7 @@ static const SpeexResampleFuncs float_funcs =
   resample_float_resampler_get_rate,
   resample_float_resampler_get_ratio,
   resample_float_resampler_get_input_latency,
+  resample_float_resampler_get_filt_len,
   resample_float_resampler_set_quality,
   resample_float_resampler_reset_mem,
   resample_float_resampler_skip_zeros,
@@ -104,6 +107,7 @@ void resample_double_resampler_get_rate (SpeexResamplerState * st,
 void resample_double_resampler_get_ratio (SpeexResamplerState * st,
     guint32 * ratio_num, guint32 * ratio_den);
 int resample_double_resampler_get_input_latency (SpeexResamplerState * st);
+int resample_double_resampler_get_filt_len (SpeexResamplerState * st);
 int resample_double_resampler_set_quality (SpeexResamplerState * st, gint quality);
 int resample_double_resampler_reset_mem (SpeexResamplerState * st);
 int resample_double_resampler_skip_zeros (SpeexResamplerState * st);
@@ -118,6 +122,7 @@ static const SpeexResampleFuncs double_funcs =
   resample_double_resampler_get_rate,
   resample_double_resampler_get_ratio,
   resample_double_resampler_get_input_latency,
+  resample_double_resampler_get_filt_len,
   resample_double_resampler_set_quality,
   resample_double_resampler_reset_mem,
   resample_double_resampler_skip_zeros,
@@ -137,6 +142,7 @@ void resample_int_resampler_get_rate (SpeexResamplerState * st,
 void resample_int_resampler_get_ratio (SpeexResamplerState * st,
     guint32 * ratio_num, guint32 * ratio_den);
 int resample_int_resampler_get_input_latency (SpeexResamplerState * st);
+int resample_int_resampler_get_filt_len (SpeexResamplerState * st);
 int resample_int_resampler_set_quality (SpeexResamplerState * st, gint quality);
 int resample_int_resampler_reset_mem (SpeexResamplerState * st);
 int resample_int_resampler_skip_zeros (SpeexResamplerState * st);
@@ -151,6 +157,7 @@ static const SpeexResampleFuncs int_funcs =
   resample_int_resampler_get_rate,
   resample_int_resampler_get_ratio,
   resample_int_resampler_get_input_latency,
+  resample_int_resampler_get_filt_len,
   resample_int_resampler_set_quality,
   resample_int_resampler_reset_mem,
   resample_int_resampler_skip_zeros,
