Merge remote-tracking branch 'origin/master' into 0.11
[platform/upstream/gstreamer.git] / gst / audioresample / gstaudioresample.c
index 80988cb..6def601 100644 (file)
@@ -28,7 +28,7 @@
  * <refsect2>
  * <title>Example launch line</title>
  * |[
- * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! audio/x-raw-int, rate=8000 ! alsasink
+ * gst-launch -v filesrc location=sine.ogg ! oggdemux ! vorbisdec ! audioconvert ! audioresample ! audio/x-raw, rate=8000 ! alsasink
  * ]| Decode an Ogg/Vorbis downsample to 8Khz and play sound through alsa.
  * To create the Ogg/Vorbis file refer to the documentation of vorbisenc.
  * </refsect2>
@@ -62,46 +62,16 @@ GST_DEBUG_CATEGORY (audio_resample_debug);
 enum
 {
   PROP_0,
-  PROP_QUALITY,
-  PROP_FILTER_LENGTH
+  PROP_QUALITY
 };
 
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
 #define SUPPORTED_CAPS \
-GST_STATIC_CAPS ( \
-    "audio/x-raw-float, " \
-      "rate = (int) [ 1, MAX ], "      \
-      "channels = (int) [ 1, MAX ], " \
-      "endianness = (int) BYTE_ORDER, " \
-      "width = (int) { 32, 64 }; " \
-    "audio/x-raw-int, " \
-      "rate = (int) [ 1, MAX ], " \
-      "channels = (int) [ 1, MAX ], " \
-      "endianness = (int) BYTE_ORDER, " \
-      "width = (int) 32, " \
-      "depth = (int) 32, " \
-      "signed = (boolean) true; " \
-    "audio/x-raw-int, " \
-      "rate = (int) [ 1, MAX ], " \
-      "channels = (int) [ 1, MAX ], " \
-      "endianness = (int) BYTE_ORDER, " \
-      "width = (int) 24, " \
-      "depth = (int) 24, " \
-      "signed = (boolean) true; " \
-    "audio/x-raw-int, " \
-      "rate = (int) [ 1, MAX ], " \
-      "channels = (int) [ 1, MAX ], " \
-      "endianness = (int) BYTE_ORDER, " \
-      "width = (int) 16, " \
-      "depth = (int) 16, " \
-      "signed = (boolean) true; " \
-    "audio/x-raw-int, " \
-      "rate = (int) [ 1, MAX ], " \
-      "channels = (int) [ 1, MAX ], " \
-      "endianness = (int) BYTE_ORDER, " \
-      "width = (int) 8, " \
-      "depth = (int) 8, " \
-      "signed = (boolean) true" \
-)
+  GST_AUDIO_CAPS_MAKE ("{ F32LE, F64LE, S32LE, S24LE, S16LE, S8 }")
+#else
+#define SUPPORTED_CAPS \
+  GST_AUDIO_CAPS_MAKE ("{ F32BE, F64BE, S32BE, S24BE, S16BE, S8 }")
+#endif
 
 /* If TRUE integer arithmetic resampling is faster and will be used if appropiate */
 #if defined AUDIORESAMPLE_FORMAT_INT
@@ -114,11 +84,15 @@ static gboolean gst_audio_resample_use_int = FALSE;
 
 static GstStaticPadTemplate gst_audio_resample_sink_template =
 GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK, GST_PAD_ALWAYS, SUPPORTED_CAPS);
+    GST_PAD_SINK,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (SUPPORTED_CAPS));
 
 static GstStaticPadTemplate gst_audio_resample_src_template =
 GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC, GST_PAD_ALWAYS, SUPPORTED_CAPS);
+    GST_PAD_SRC,
+    GST_PAD_ALWAYS,
+    GST_STATIC_CAPS (SUPPORTED_CAPS));
 
 static void gst_audio_resample_set_property (GObject * object,
     guint prop_id, const GValue * value, GParamSpec * pspec);
@@ -127,47 +101,33 @@ static void gst_audio_resample_get_property (GObject * object,
 
 /* vmethods */
 static gboolean gst_audio_resample_get_unit_size (GstBaseTransform * base,
-    GstCaps * caps, guint * size);
+    GstCaps * caps, gsize * size);
 static GstCaps *gst_audio_resample_transform_caps (GstBaseTransform * base,
-    GstPadDirection direction, GstCaps * caps);
+    GstPadDirection direction, GstCaps * caps, GstCaps * filter);
 static void gst_audio_resample_fixate_caps (GstBaseTransform * base,
     GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
 static gboolean gst_audio_resample_transform_size (GstBaseTransform * trans,
-    GstPadDirection direction, GstCaps * incaps, guint insize,
-    GstCaps * outcaps, guint * outsize);
+    GstPadDirection direction, GstCaps * incaps, gsize insize,
+    GstCaps * outcaps, gsize * outsize);
 static gboolean gst_audio_resample_set_caps (GstBaseTransform * base,
     GstCaps * incaps, GstCaps * outcaps);
 static GstFlowReturn gst_audio_resample_transform (GstBaseTransform * base,
     GstBuffer * inbuf, GstBuffer * outbuf);
-static gboolean gst_audio_resample_event (GstBaseTransform * base,
+static gboolean gst_audio_resample_sink_event (GstBaseTransform * base,
     GstEvent * event);
 static gboolean gst_audio_resample_start (GstBaseTransform * base);
 static gboolean gst_audio_resample_stop (GstBaseTransform * base);
-static gboolean gst_audio_resample_query (GstPad * pad, GstQuery * query);
-static const GstQueryType *gst_audio_resample_query_type (GstPad * pad);
-
-GST_BOILERPLATE (GstAudioResample, gst_audio_resample, GstBaseTransform,
-    GST_TYPE_BASE_TRANSFORM);
-
-static void
-gst_audio_resample_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_static_pad_template (gstelement_class,
-      &gst_audio_resample_src_template);
-  gst_element_class_add_static_pad_template (gstelement_class,
-      &gst_audio_resample_sink_template);
+static gboolean gst_audio_resample_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 
-  gst_element_class_set_details_simple (gstelement_class, "Audio resampler",
-      "Filter/Converter/Audio", "Resamples audio",
-      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
-}
+#define gst_audio_resample_parent_class parent_class
+G_DEFINE_TYPE (GstAudioResample, gst_audio_resample, GST_TYPE_BASE_TRANSFORM);
 
 static void
 gst_audio_resample_class_init (GstAudioResampleClass * klass)
 {
   GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstElementClass *gstelement_class = (GstElementClass *) klass;
 
   gobject_class->set_property = gst_audio_resample_set_property;
   gobject_class->get_property = gst_audio_resample_get_property;
@@ -179,20 +139,14 @@ gst_audio_resample_class_init (GstAudioResampleClass * klass)
           SPEEX_RESAMPLER_QUALITY_DEFAULT,
           G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
 
-  /* FIXME 0.11: Remove this property, it's just for compatibility
-   * with old audioresample
-   */
-  /**
-   * GstAudioResample:filter-length:
-   *
-   * Length of the resample filter
-   *
-   * Deprectated: Use #GstAudioResample:quality property instead
-   */
-  g_object_class_install_property (gobject_class, PROP_FILTER_LENGTH,
-      g_param_spec_int ("filter-length", "Filter length",
-          "Length of the resample filter", 0, G_MAXINT, 64,
-          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&gst_audio_resample_src_template));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&gst_audio_resample_sink_template));
+
+  gst_element_class_set_details_simple (gstelement_class, "Audio resampler",
+      "Filter/Converter/Audio", "Resamples audio",
+      "Sebastian Dröge <sebastian.droege@collabora.co.uk>");
 
   GST_BASE_TRANSFORM_CLASS (klass)->start =
       GST_DEBUG_FUNCPTR (gst_audio_resample_start);
@@ -210,15 +164,14 @@ gst_audio_resample_class_init (GstAudioResampleClass * klass)
       GST_DEBUG_FUNCPTR (gst_audio_resample_set_caps);
   GST_BASE_TRANSFORM_CLASS (klass)->transform =
       GST_DEBUG_FUNCPTR (gst_audio_resample_transform);
-  GST_BASE_TRANSFORM_CLASS (klass)->event =
-      GST_DEBUG_FUNCPTR (gst_audio_resample_event);
+  GST_BASE_TRANSFORM_CLASS (klass)->sink_event =
+      GST_DEBUG_FUNCPTR (gst_audio_resample_sink_event);
 
   GST_BASE_TRANSFORM_CLASS (klass)->passthrough_on_same_caps = TRUE;
 }
 
 static void
-gst_audio_resample_init (GstAudioResample * resample,
-    GstAudioResampleClass * klass)
+gst_audio_resample_init (GstAudioResample * resample)
 {
   GstBaseTransform *trans = GST_BASE_TRANSFORM (resample);
 
@@ -226,8 +179,6 @@ gst_audio_resample_init (GstAudioResample * resample,
 
   gst_base_transform_set_gap_aware (trans, TRUE);
   gst_pad_set_query_function (trans->srcpad, gst_audio_resample_query);
-  gst_pad_set_query_type_function (trans->srcpad,
-      gst_audio_resample_query_type);
 }
 
 /* vmethods */
@@ -274,68 +225,82 @@ gst_audio_resample_stop (GstBaseTransform * base)
   resample->tmp_out = NULL;
   resample->tmp_out_size = 0;
 
-  gst_caps_replace (&resample->sinkcaps, NULL);
-  gst_caps_replace (&resample->srccaps, NULL);
-
   return TRUE;
 }
 
 static gboolean
 gst_audio_resample_get_unit_size (GstBaseTransform * base, GstCaps * caps,
-    guint * size)
+    gsize * size)
 {
-  gint width, channels;
-  GstStructure *structure;
-  gboolean ret;
+  GstAudioInfo info;
 
-  g_return_val_if_fail (size != NULL, FALSE);
+  if (!gst_audio_info_from_caps (&info, caps))
+    goto invalid_caps;
 
-  /* this works for both float and int */
-  structure = gst_caps_get_structure (caps, 0);
-  ret = gst_structure_get_int (structure, "width", &width);
-  ret &= gst_structure_get_int (structure, "channels", &channels);
-
-  if (G_UNLIKELY (!ret))
-    return FALSE;
-
-  *size = (width / 8) * channels;
+  *size = GST_AUDIO_INFO_BPF (&info);
 
   return TRUE;
+
+  /* ERRORS */
+invalid_caps:
+  {
+    GST_ERROR_OBJECT (base, "invalid caps");
+    return FALSE;
+  }
 }
 
 static GstCaps *
 gst_audio_resample_transform_caps (GstBaseTransform * base,
-    GstPadDirection direction, GstCaps * caps)
+    GstPadDirection direction, GstCaps * caps, GstCaps * filter)
 {
   const GValue *val;
   GstStructure *s;
   GstCaps *res;
+  gint i, n;
 
   /* transform single caps into input_caps + input_caps with the rate
    * field set to our supported range. This ensures that upstream knows
    * about downstream's prefered rate(s) and can negotiate accordingly. */
-  res = gst_caps_copy (caps);
-
-  /* first, however, check if the caps contain a range for the rate field, in
-   * which case that side isn't going to care much about the exact sample rate
-   * chosen and we should just assume things will get fixated to something sane
-   * and we may just as well offer our full range instead of the range in the
-   * caps. If the rate is not an int range value, it's likely to express a
-   * real preference or limitation and we should maintain that structure as
-   * preference by putting it first into the transformed caps, and only add
-   * our full rate range as second option  */
-  s = gst_caps_get_structure (res, 0);
-  val = gst_structure_get_value (s, "rate");
-  if (val == NULL || GST_VALUE_HOLDS_INT_RANGE (val)) {
-    /* overwrite existing range, or add field if it doesn't exist yet */
-    gst_structure_set (s, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
-  } else {
-    /* append caps with full range to existing caps with non-range rate field */
+  res = gst_caps_new_empty ();
+  n = gst_caps_get_size (caps);
+  for (i = 0; i < n; i++) {
+    s = gst_caps_get_structure (caps, i);
+
+    /* If this is already expressed by the existing caps
+     * skip this structure */
+    if (i > 0 && gst_caps_is_subset_structure (res, s))
+      continue;
+
+    /* first, however, check if the caps contain a range for the rate field, in
+     * which case that side isn't going to care much about the exact sample rate
+     * chosen and we should just assume things will get fixated to something sane
+     * and we may just as well offer our full range instead of the range in the
+     * caps. If the rate is not an int range value, it's likely to express a
+     * real preference or limitation and we should maintain that structure as
+     * preference by putting it first into the transformed caps, and only add
+     * our full rate range as second option  */
     s = gst_structure_copy (s);
-    gst_structure_set (s, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
+    val = gst_structure_get_value (s, "rate");
+    if (val == NULL || GST_VALUE_HOLDS_INT_RANGE (val)) {
+      /* overwrite existing range, or add field if it doesn't exist yet */
+      gst_structure_set (s, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
+    } else {
+      /* append caps with full range to existing caps with non-range rate field */
+      gst_caps_append_structure (res, gst_structure_copy (s));
+      gst_structure_set (s, "rate", GST_TYPE_INT_RANGE, 1, G_MAXINT, NULL);
+    }
     gst_caps_append_structure (res, s);
   }
 
+  if (filter) {
+    GstCaps *intersection;
+
+    intersection =
+        gst_caps_intersect_full (filter, res, GST_CAPS_INTERSECT_FIRST);
+    gst_caps_unref (res);
+    res = intersection;
+  }
+
   return res;
 }
 
@@ -458,63 +423,6 @@ gst_audio_resample_reset_state (GstAudioResample * resample)
     resample->funcs->reset_mem (resample->state);
 }
 
-static gboolean
-gst_audio_resample_parse_caps (GstCaps * incaps,
-    GstCaps * outcaps, gint * width, gint * channels, gint * inrate,
-    gint * outrate, gboolean * fp)
-{
-  GstStructure *structure;
-  gboolean ret;
-  gint mywidth, myinrate, myoutrate, mychannels;
-  gboolean myfp;
-
-  GST_DEBUG ("incaps %" GST_PTR_FORMAT ", outcaps %"
-      GST_PTR_FORMAT, incaps, outcaps);
-
-  structure = gst_caps_get_structure (incaps, 0);
-
-  if (gst_structure_has_name (structure, "audio/x-raw-float"))
-    myfp = TRUE;
-  else
-    myfp = FALSE;
-
-  ret = gst_structure_get_int (structure, "rate", &myinrate);
-  ret &= gst_structure_get_int (structure, "channels", &mychannels);
-  ret &= gst_structure_get_int (structure, "width", &mywidth);
-  if (G_UNLIKELY (!ret))
-    goto no_in_rate_channels;
-
-  structure = gst_caps_get_structure (outcaps, 0);
-  ret = gst_structure_get_int (structure, "rate", &myoutrate);
-  if (G_UNLIKELY (!ret))
-    goto no_out_rate;
-
-  if (channels)
-    *channels = mychannels;
-  if (inrate)
-    *inrate = myinrate;
-  if (outrate)
-    *outrate = myoutrate;
-  if (width)
-    *width = mywidth;
-  if (fp)
-    *fp = myfp;
-
-  return TRUE;
-
-  /* ERRORS */
-no_in_rate_channels:
-  {
-    GST_DEBUG ("could not get input rate and channels");
-    return FALSE;
-  }
-no_out_rate:
-  {
-    GST_DEBUG ("could not get output rate");
-    return FALSE;
-  }
-}
-
 static gint
 _gcd (gint a, gint b)
 {
@@ -530,30 +438,33 @@ _gcd (gint a, gint b)
 
 static gboolean
 gst_audio_resample_transform_size (GstBaseTransform * base,
-    GstPadDirection direction, GstCaps * caps, guint size, GstCaps * othercaps,
-    guint * othersize)
+    GstPadDirection direction, GstCaps * caps, gsize size, GstCaps * othercaps,
+    gsize * othersize)
 {
   gboolean ret = TRUE;
+  GstAudioInfo in, out;
   guint32 ratio_den, ratio_num;
   gint inrate, outrate, gcd;
-  gint bytes_per_samp, channels;
+  gint bpf;
 
-  GST_LOG_OBJECT (base, "asked to transform size %d in direction %s",
-      size, direction == GST_PAD_SINK ? "SINK" : "SRC");
+  GST_LOG_OBJECT (base, "asked to transform size %" G_GSIZE_FORMAT
+      " in direction %s", size, direction == GST_PAD_SINK ? "SINK" : "SRC");
 
   /* Get sample width -> bytes_per_samp, channels, inrate, outrate */
-  ret =
-      gst_audio_resample_parse_caps (caps, othercaps, &bytes_per_samp,
-      &channels, &inrate, &outrate, NULL);
+  ret = gst_audio_info_from_caps (&in, caps);
+  ret &= gst_audio_info_from_caps (&out, othercaps);
   if (G_UNLIKELY (!ret)) {
     GST_ERROR_OBJECT (base, "Wrong caps");
     return FALSE;
   }
   /* Number of samples in either buffer is size / (width*channels) ->
    * calculate the factor */
-  bytes_per_samp = bytes_per_samp * channels / 8;
+  bpf = GST_AUDIO_INFO_BPF (&in);
+  inrate = GST_AUDIO_INFO_RATE (&in);
+  outrate = GST_AUDIO_INFO_RATE (&out);
+
   /* Convert source buffer size to samples */
-  size /= bytes_per_samp;
+  size /= bpf;
 
   /* Simplify the conversion ratio factors */
   gcd = _gcd (inrate, outrate);
@@ -563,15 +474,16 @@ gst_audio_resample_transform_size (GstBaseTransform * base,
   if (direction == GST_PAD_SINK) {
     /* asked to convert size of an incoming buffer. Round up the output size */
     *othersize = gst_util_uint64_scale_int_ceil (size, ratio_den, ratio_num);
-    *othersize *= bytes_per_samp;
+    *othersize *= bpf;
   } else {
     /* asked to convert size of an outgoing buffer. Round down the input size */
     *othersize = gst_util_uint64_scale_int (size, ratio_num, ratio_den);
-    *othersize *= bytes_per_samp;
+    *othersize *= bpf;
   }
 
-  GST_LOG_OBJECT (base, "transformed size %d to %d", size * bytes_per_samp,
-      *othersize);
+  GST_LOG_OBJECT (base,
+      "transformed size %" G_GSIZE_FORMAT " to %" G_GSIZE_FORMAT,
+      size * bpf, *othersize);
 
   return ret;
 }
@@ -581,18 +493,27 @@ gst_audio_resample_set_caps (GstBaseTransform * base, GstCaps * incaps,
     GstCaps * outcaps)
 {
   gboolean ret;
-  gint width = 0, inrate = 0, outrate = 0, channels = 0;
+  gint width, inrate, outrate, channels;
   gboolean fp;
   GstAudioResample *resample = GST_AUDIO_RESAMPLE (base);
+  GstAudioInfo in, out;
 
   GST_LOG ("incaps %" GST_PTR_FORMAT ", outcaps %"
       GST_PTR_FORMAT, incaps, outcaps);
 
-  ret = gst_audio_resample_parse_caps (incaps, outcaps,
-      &width, &channels, &inrate, &outrate, &fp);
+  if (!gst_audio_info_from_caps (&in, incaps))
+    goto invalid_incaps;
+  if (!gst_audio_info_from_caps (&out, outcaps))
+    goto invalid_outcaps;
 
-  if (G_UNLIKELY (!ret))
-    return FALSE;
+  /* FIXME do some checks */
+
+  /* take new values */
+  width = GST_AUDIO_FORMAT_INFO_WIDTH (in.finfo);
+  channels = GST_AUDIO_INFO_CHANNELS (&in);
+  inrate = GST_AUDIO_INFO_RATE (&in);
+  outrate = GST_AUDIO_INFO_RATE (&out);
+  fp = GST_AUDIO_FORMAT_INFO_IS_FLOAT (in.finfo);
 
   ret =
       gst_audio_resample_update_state (resample, width, channels, inrate,
@@ -601,12 +522,19 @@ gst_audio_resample_set_caps (GstBaseTransform * base, GstCaps * incaps,
   if (G_UNLIKELY (!ret))
     return FALSE;
 
-  /* save caps so we can short-circuit in the size_transform if the caps
-   * are the same */
-  gst_caps_replace (&resample->sinkcaps, incaps);
-  gst_caps_replace (&resample->srccaps, outcaps);
-
   return TRUE;
+
+  /* ERROR */
+invalid_incaps:
+  {
+    GST_ERROR_OBJECT (base, "invalid incaps");
+    return FALSE;
+  }
+invalid_outcaps:
+  {
+    GST_ERROR_OBJECT (base, "invalid outcaps");
+    return FALSE;
+  }
 }
 
 #define GST_MAXINT24 (8388607)
@@ -824,6 +752,7 @@ gst_audio_resample_push_drain (GstAudioResample * resample, guint history_len)
   guint out_len, out_processed;
   gint err;
   guint num, den;
+  guint8 *data;
 
   g_assert (resample->state != NULL);
 
@@ -841,15 +770,9 @@ gst_audio_resample_push_drain (GstAudioResample * resample, guint history_len)
   if (out_len == 0)
     return;
 
-  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;
-  }
+  outbuf = gst_buffer_new_and_alloc (outsize);
+
+  data = gst_buffer_map (outbuf, NULL, NULL, GST_MAP_WRITE);
 
   if (resample->funcs->width != resample->width) {
     /* need to convert data format;  allocate workspace */
@@ -866,17 +789,20 @@ gst_audio_resample_push_drain (GstAudioResample * resample, guint history_len)
 
     /* convert output format */
     gst_audio_resample_convert_buffer (resample, resample->tmp_out,
-        GST_BUFFER_DATA (outbuf), out_processed, TRUE);
+        data, out_processed, TRUE);
   } else {
     /* don't need to convert data format;  process */
     err = resample->funcs->process (resample->state, NULL, &in_processed,
-        GST_BUFFER_DATA (outbuf), &out_processed);
+        data, &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);
 
+  outsize = out_processed * resample->channels * (resample->width / 8);
+  gst_buffer_unmap (outbuf, data, outsize);
+
   if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
     GST_WARNING_OBJECT (resample, "Failed to process drain: %s",
         resample->funcs->strerror (err));
@@ -914,13 +840,10 @@ gst_audio_resample_push_drain (GstAudioResample * resample, guint history_len)
     return;
   }
 
-  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 (outbuf),
+      G_GUINT64_FORMAT, outsize,
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)), GST_BUFFER_OFFSET (outbuf),
       GST_BUFFER_OFFSET_END (outbuf));
@@ -935,7 +858,7 @@ gst_audio_resample_push_drain (GstAudioResample * resample, guint history_len)
 }
 
 static gboolean
-gst_audio_resample_event (GstBaseTransform * base, GstEvent * event)
+gst_audio_resample_sink_event (GstBaseTransform * base, GstEvent * event)
 {
   GstAudioResample *resample = GST_AUDIO_RESAMPLE (base);
 
@@ -953,7 +876,7 @@ gst_audio_resample_event (GstBaseTransform * base, GstEvent * event)
       resample->samples_out = 0;
       resample->need_discont = TRUE;
       break;
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
       if (resample->state) {
         guint latency = resample->funcs->get_input_latency (resample->state);
         gst_audio_resample_push_drain (resample, latency);
@@ -981,7 +904,7 @@ gst_audio_resample_event (GstBaseTransform * base, GstEvent * event)
       break;
   }
 
-  return parent_class->event (base, event);
+  return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (base, event);
 }
 
 static gboolean
@@ -1025,12 +948,17 @@ static GstFlowReturn
 gst_audio_resample_process (GstAudioResample * resample, GstBuffer * inbuf,
     GstBuffer * outbuf)
 {
+  gsize in_size, out_size;
+  guint8 *in_data, *out_data;
   guint32 in_len, in_processed;
   guint32 out_len, out_processed;
   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;
+  in_data = gst_buffer_map (inbuf, &in_size, NULL, GST_MAP_READ);
+  out_data = gst_buffer_map (outbuf, &out_size, NULL, GST_MAP_WRITE);
+
+  in_len = in_size / resample->channels;
+  out_len = out_size / resample->channels;
 
   in_len /= (resample->width / 8);
   out_len /= (resample->width / 8);
@@ -1062,7 +990,7 @@ gst_audio_resample_process (GstAudioResample * resample, GstBuffer * inbuf,
       else
         out_processed = 0;
 
-      memset (GST_BUFFER_DATA (outbuf), 0, GST_BUFFER_SIZE (outbuf));
+      memset (out_data, 0, out_size);
       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_GAP);
       resample->num_gap_samples += in_len;
       in_processed = in_len;
@@ -1095,11 +1023,13 @@ gst_audio_resample_process (GstAudioResample * resample, GstBuffer * inbuf,
               &resample->tmp_out_size, out_len * resample->channels *
               (resample->funcs->width / 8))) {
         GST_ERROR_OBJECT (resample, "failed to allocate workspace");
+        gst_buffer_unmap (inbuf, in_data, in_size);
+        gst_buffer_unmap (outbuf, out_data, out_size);
         return GST_FLOW_ERROR;
       }
 
       /* convert input */
-      gst_audio_resample_convert_buffer (resample, GST_BUFFER_DATA (inbuf),
+      gst_audio_resample_convert_buffer (resample, in_data,
           resample->tmp_in, in_len, FALSE);
 
       /* process */
@@ -1108,17 +1038,18 @@ gst_audio_resample_process (GstAudioResample * resample, GstBuffer * inbuf,
 
       /* convert output */
       gst_audio_resample_convert_buffer (resample, resample->tmp_out,
-          GST_BUFFER_DATA (outbuf), out_processed, TRUE);
+          out_data, 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);
+          in_data, &in_processed, out_data, &out_processed);
     }
 
     if (G_UNLIKELY (err != RESAMPLER_ERR_SUCCESS)) {
       GST_ERROR_OBJECT (resample, "Failed to convert data: %s",
           resample->funcs->strerror (err));
+      gst_buffer_unmap (inbuf, in_data, in_size);
+      gst_buffer_unmap (outbuf, out_data, out_size);
       return GST_FLOW_ERROR;
     }
   }
@@ -1156,14 +1087,15 @@ gst_audio_resample_process (GstAudioResample * resample, GstBuffer * inbuf,
   resample->samples_out += out_processed;
   resample->samples_in += in_len;
 
-  GST_BUFFER_SIZE (outbuf) =
-      out_processed * resample->channels * (resample->width / 8);
+  out_size = out_processed * resample->channels * (resample->width / 8);
+  gst_buffer_unmap (inbuf, in_data, in_size);
+  gst_buffer_unmap (outbuf, out_data, out_size);
 
   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),
+      " samples (%" G_GSIZE_FORMAT " bytes) with timestamp %" GST_TIME_FORMAT
+      ", duration %" GST_TIME_FORMAT ", offset %" G_GUINT64_FORMAT
+      ", offset_end %" G_GUINT64_FORMAT, out_processed, out_size,
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)),
       GST_BUFFER_OFFSET (outbuf), GST_BUFFER_OFFSET_END (outbuf));
@@ -1176,7 +1108,6 @@ gst_audio_resample_transform (GstBaseTransform * base, GstBuffer * inbuf,
     GstBuffer * outbuf)
 {
   GstAudioResample *resample = GST_AUDIO_RESAMPLE (base);
-  gulong size;
   GstFlowReturn ret;
 
   if (resample->state == NULL) {
@@ -1190,12 +1121,10 @@ gst_audio_resample_transform (GstBaseTransform * base, GstBuffer * inbuf,
         gst_audio_resample_get_funcs (resample->width, resample->fp);
   }
 
-  size = GST_BUFFER_SIZE (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 (GST_BUFFER_TIMESTAMP (inbuf)),
+      gst_buffer_get_size (inbuf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)),
       GST_BUFFER_OFFSET (inbuf), GST_BUFFER_OFFSET_END (inbuf));
 
@@ -1257,13 +1186,11 @@ gst_audio_resample_transform (GstBaseTransform * base, GstBuffer * inbuf,
 }
 
 static gboolean
-gst_audio_resample_query (GstPad * pad, GstQuery * query)
+gst_audio_resample_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
-  GstAudioResample *resample = GST_AUDIO_RESAMPLE (gst_pad_get_parent (pad));
+  GstAudioResample *resample = GST_AUDIO_RESAMPLE (parent);
   GstBaseTransform *trans;
   gboolean res = TRUE;
-  if (G_UNLIKELY (resample == NULL))
-    return FALSE;
 
   trans = GST_BASE_TRANSFORM (resample);
 
@@ -1273,7 +1200,6 @@ gst_audio_resample_query (GstPad * pad, GstQuery * query)
       GstClockTime min, max;
       gboolean live;
       guint64 latency;
-      GstPad *peer;
       gint rate = resample->inrate;
       gint resampler_latency;
 
@@ -1286,57 +1212,44 @@ gst_audio_resample_query (GstPad * pad, GstQuery * query)
       if (gst_base_transform_is_passthrough (trans))
         resampler_latency = 0;
 
-      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);
+      if ((res =
+              gst_pad_peer_query (GST_BASE_TRANSFORM_SINK_PAD (trans),
+                  query))) {
+        gst_query_parse_latency (query, &live, &min, &max);
 
-          GST_DEBUG_OBJECT (resample, "Peer latency: min %"
-              GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
-              GST_TIME_ARGS (min), GST_TIME_ARGS (max));
+        GST_DEBUG_OBJECT (resample, "Peer latency: min %"
+            GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (min), GST_TIME_ARGS (max));
 
-          /* add our own latency */
-          if (rate != 0 && resampler_latency != 0)
-            latency = gst_util_uint64_scale_round (resampler_latency,
-                GST_SECOND, rate);
-          else
-            latency = 0;
+        /* add our own latency */
+        if (rate != 0 && resampler_latency != 0)
+          latency = gst_util_uint64_scale_round (resampler_latency,
+              GST_SECOND, rate);
+        else
+          latency = 0;
 
-          GST_DEBUG_OBJECT (resample, "Our latency: %" GST_TIME_FORMAT,
-              GST_TIME_ARGS (latency));
+        GST_DEBUG_OBJECT (resample, "Our latency: %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (latency));
 
-          min += latency;
-          if (GST_CLOCK_TIME_IS_VALID (max))
-            max += latency;
+        min += latency;
+        if (GST_CLOCK_TIME_IS_VALID (max))
+          max += latency;
 
-          GST_DEBUG_OBJECT (resample, "Calculated total latency : min %"
-              GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
-              GST_TIME_ARGS (min), GST_TIME_ARGS (max));
+        GST_DEBUG_OBJECT (resample, "Calculated total latency : min %"
+            GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
+            GST_TIME_ARGS (min), GST_TIME_ARGS (max));
 
-          gst_query_set_latency (query, live, min, max);
-        }
-        gst_object_unref (peer);
+        gst_query_set_latency (query, live, min, max);
       }
       break;
     }
     default:
-      res = gst_pad_query_default (pad, query);
+      res = gst_pad_query_default (pad, parent, query);
       break;
   }
-  gst_object_unref (resample);
   return res;
 }
 
-static const GstQueryType *
-gst_audio_resample_query_type (GstPad * pad)
-{
-  static const GstQueryType types[] = {
-    GST_QUERY_LATENCY,
-    0
-  };
-
-  return types;
-}
-
 static void
 gst_audio_resample_set_property (GObject * object, guint prop_id,
     const GValue * value, GParamSpec * pspec)
@@ -1357,41 +1270,6 @@ gst_audio_resample_set_property (GObject * object, guint prop_id,
           quality, resample->fp);
       GST_BASE_TRANSFORM_UNLOCK (resample);
       break;
-    case PROP_FILTER_LENGTH:{
-      gint filter_length = g_value_get_int (value);
-
-      GST_BASE_TRANSFORM_LOCK (resample);
-      if (filter_length <= 8)
-        quality = 0;
-      else if (filter_length <= 16)
-        quality = 1;
-      else if (filter_length <= 32)
-        quality = 2;
-      else if (filter_length <= 48)
-        quality = 3;
-      else if (filter_length <= 64)
-        quality = 4;
-      else if (filter_length <= 80)
-        quality = 5;
-      else if (filter_length <= 96)
-        quality = 6;
-      else if (filter_length <= 128)
-        quality = 7;
-      else if (filter_length <= 160)
-        quality = 8;
-      else if (filter_length <= 192)
-        quality = 9;
-      else
-        quality = 10;
-
-      GST_DEBUG_OBJECT (resample, "new quality %d", quality);
-
-      gst_audio_resample_update_state (resample, resample->width,
-          resample->channels, resample->inrate, resample->outrate,
-          quality, resample->fp);
-      GST_BASE_TRANSFORM_UNLOCK (resample);
-      break;
-    }
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;
@@ -1410,43 +1288,6 @@ gst_audio_resample_get_property (GObject * object, guint prop_id,
     case PROP_QUALITY:
       g_value_set_int (value, resample->quality);
       break;
-    case PROP_FILTER_LENGTH:
-      switch (resample->quality) {
-        case 0:
-          g_value_set_int (value, 8);
-          break;
-        case 1:
-          g_value_set_int (value, 16);
-          break;
-        case 2:
-          g_value_set_int (value, 32);
-          break;
-        case 3:
-          g_value_set_int (value, 48);
-          break;
-        case 4:
-          g_value_set_int (value, 64);
-          break;
-        case 5:
-          g_value_set_int (value, 80);
-          break;
-        case 6:
-          g_value_set_int (value, 96);
-          break;
-        case 7:
-          g_value_set_int (value, 128);
-          break;
-        case 8:
-          g_value_set_int (value, 160);
-          break;
-        case 9:
-          g_value_set_int (value, 192);
-          break;
-        case 10:
-          g_value_set_int (value, 256);
-          break;
-      }
-      break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
       break;