? gstspeed.c-bak
? patch
Index: gstspeed.c
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-bad/gst/speed/gstspeed.c,v
retrieving revision 1.38
diff -u -p -r1.38 gstspeed.c
--- gstspeed.c	8 Sep 2005 15:56:38 -0000	1.38
+++ gstspeed.c	7 Oct 2005 19:28:00 -0000
@@ -30,111 +30,117 @@
 #include "gstspeed.h"
 
 /* elementfactory information */
-static GstElementDetails speed_details = GST_ELEMENT_DETAILS ("Speed",
-    "Filter/Effect/Audio",
-    "Set speed/pitch on audio/raw streams (resampler)",
-    "Andy Wingo <apwingo@eos.ncsu.edu>, "
-    "Tim-Philipp Müller <tim@centricular.net>");
+static GstElementDetails speed_details =
+  GST_ELEMENT_DETAILS ("Speed",
+		       "Filter/Effect/Audio",
+		       "Set speed/pitch on audio/raw streams (resampler)",
+		       "Andy Wingo <apwingo@eos.ncsu.edu>, "
+		       "Tim-Philipp Müller <tim@centricular.net>");
 
 
 enum
-{
-  ARG_0,
-  ARG_SPEED
-};
+  {
+    ARG_0,
+    ARG_SPEED
+  };
 
 /* assumption here: sizeof (gfloat) = 4 */
-#define GST_SPEED_AUDIO_CAPS \
-    "audio/x-raw-float, " \
-    "rate = (int) [ 1, MAX ], " \
-    "channels = (int) [ 1, MAX ], " \
-    "endianness = (int) BYTE_ORDER, " \
-    "width = (int) 32, " \
-    "buffer-frames = (int) 0; " \
-    \
-    "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"
+#define GST_SPEED_AUDIO_CAPS			\
+  "audio/x-raw-float, "				\
+  "rate = (int) [ 1, MAX ], "			\
+  "channels = (int) [ 1, MAX ], "		\
+  "endianness = (int) BYTE_ORDER, "		\
+  "width = (int) 32; "				\
+						\
+  "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"
 
 static GstStaticPadTemplate gst_speed_sink_template =
-GST_STATIC_PAD_TEMPLATE ("sink",
-    GST_PAD_SINK,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_SPEED_AUDIO_CAPS)
-    );
+  GST_STATIC_PAD_TEMPLATE ("sink",
+			   GST_PAD_SINK,
+			   GST_PAD_ALWAYS,
+			   GST_STATIC_CAPS (GST_SPEED_AUDIO_CAPS)
+			   );
 
 static GstStaticPadTemplate gst_speed_src_template =
-GST_STATIC_PAD_TEMPLATE ("src",
-    GST_PAD_SRC,
-    GST_PAD_ALWAYS,
-    GST_STATIC_CAPS (GST_SPEED_AUDIO_CAPS)
-    );
+  GST_STATIC_PAD_TEMPLATE ("src",
+			   GST_PAD_SRC,
+			   GST_PAD_ALWAYS,
+			   GST_STATIC_CAPS (GST_SPEED_AUDIO_CAPS)
+			   );
 
 static void speed_base_init (gpointer g_class);
 static void speed_class_init (GstSpeedClass * klass);
 static void speed_init (GstSpeed * filter);
 
 static void speed_set_property (GObject * object, guint prop_id,
-    const GValue * value, GParamSpec * pspec);
+				const GValue * value, GParamSpec * pspec);
 static void speed_get_property (GObject * object, guint prop_id, GValue * value,
-    GParamSpec * pspec);
+				GParamSpec * pspec);
 
 static gboolean speed_parse_caps (GstSpeed * filter, const GstCaps * caps);
 
 static GstFlowReturn speed_chain (GstPad * pad, GstBuffer * buf);
 
-static GstStateChangeReturn speed_change_state (GstElement * element,
-    GstStateChange transition);
+static GstStateChangeReturn speed_change_state (GstElement * element, GstStateChange transition);
+
+static gboolean speed_sink_event (GstPad * pad, GstEvent * event);
+static gboolean speed_src_event (GstPad * pad, GstEvent * event);
 
 static GstElementClass *parent_class;   /* NULL */
 
 static gboolean
-gst_speed_setcaps (GstPad * pad, GstCaps * caps)
+speed_setcaps (GstPad * pad, GstCaps * caps)
 {
   GstSpeed *filter;
   GstPad *otherpad;
 
-  filter = GST_SPEED (gst_pad_get_parent (pad));
-  g_return_val_if_fail (filter != NULL, GST_PAD_LINK_REFUSED);
-  g_return_val_if_fail (GST_IS_SPEED (filter), GST_PAD_LINK_REFUSED);
+  filter = GST_SPEED ( GST_PAD_PARENT (pad));
+
   otherpad = (pad == filter->srcpad) ? filter->sinkpad : filter->srcpad;
 
-  if (!speed_parse_caps (filter, caps))
-    return GST_PAD_LINK_REFUSED;
+  if (!speed_parse_caps (filter, caps)) {
+    return FALSE;
+  }
 
   return gst_pad_set_caps (otherpad, caps);
+
 }
 
 static gboolean
 speed_parse_caps (GstSpeed * filter, const GstCaps * caps)
 {
-  const gchar *mimetype;
   GstStructure *structure;
-  gboolean ret;
+  gint rate, chans, width;
 
   g_return_val_if_fail (filter != NULL, FALSE);
   g_return_val_if_fail (caps != NULL, FALSE);
 
   structure = gst_caps_get_structure (caps, 0);
 
-  mimetype = gst_structure_get_name (structure);
-  if (strcmp (mimetype, "audio/x-raw-float") == 0)
+  if ( gst_structure_has_name (structure, "audio/x-raw-float") )
     filter->format = GST_SPEED_FORMAT_FLOAT;
-  else if (strcmp (mimetype, "audio/x-raw-int") == 0)
+
+  else if ( gst_structure_has_name (structure, "audio/x-raw-int") )
     filter->format = GST_SPEED_FORMAT_INT;
-  else
+  else {
     return FALSE;
+  }
 
-  ret = gst_structure_get_int (structure, "rate", &filter->rate);
-  ret &= gst_structure_get_int (structure, "channels", &filter->channels);
-  ret &= gst_structure_get_int (structure, "width", &filter->width);
+  if (!gst_structure_get_int (structure, "rate", &rate)
+      || !gst_structure_get_int (structure, "width", &width)
+      || !gst_structure_get_int (structure, "channels", &chans)) {
+    return FALSE;
+  }
 
-  filter->buffer_frames = 0;
-  gst_structure_get_int (structure, "buffer-frames", &filter->buffer_frames);
+  filter->rate = rate;
+  filter->width = width;
+  filter->channels = chans;
 
   if (filter->format == GST_SPEED_FORMAT_FLOAT) {
     filter->sample_size = filter->channels * filter->width / 8;
@@ -143,7 +149,7 @@ speed_parse_caps (GstSpeed * filter, con
     filter->sample_size = filter->channels * filter->width / 8;
   }
 
-  return ret;
+  return TRUE;
 }
 
 GType
@@ -165,7 +171,7 @@ gst_speed_get_type (void)
     };
 
     speed_type =
-        g_type_register_static (GST_TYPE_ELEMENT, "GstSpeed", &speed_info, 0);
+      g_type_register_static (GST_TYPE_ELEMENT, "GstSpeed", &speed_info, 0);
   }
   return speed_type;
 }
@@ -182,26 +188,276 @@ speed_get_query_types (GstPad * pad)
 }
 
 static gboolean
-speed_src_query (GstPad * pad, GstQuery * query)
+speed_src_event (GstPad * pad, GstEvent * event)
 {
-  gboolean res = TRUE;
   GstSpeed *filter;
 
-  filter = GST_SPEED (gst_pad_get_parent (pad));
+  filter = GST_SPEED ( GST_PAD_PARENT (pad));
 
-  switch (GST_QUERY_TYPE (query)) {
-    case GST_QUERY_POSITION:
+  switch (GST_EVENT_TYPE (event)) {
+  case GST_EVENT_SEEK:
     {
+
+      gdouble rate;
+      GstFormat format;
+      GstSeekFlags flags;
+      GstSeekType start_type, stop_type;
+      gint64 start, stop;
+
+      gst_event_parse_seek (event, &rate, &format, &flags,
+			    &start_type, &start, &stop_type, &stop);
+      switch (format) {
+      case GST_FORMAT_DEFAULT:
+	/* fall through */
+      case GST_FORMAT_BYTES:
+	/* fall through */
+      case GST_FORMAT_TIME:
+	gst_event_unref (event);
+
+	if ( start_type != GST_SEEK_TYPE_NONE ) {
+	  start *= filter->speed;
+	}
+
+	if ( stop_type != GST_SEEK_TYPE_NONE ) {
+	  stop *= filter->speed;
+	}
+
+	event = gst_event_new_seek (rate, format, flags, start_type, start,
+				    stop_type, stop);
+	
+	return gst_pad_send_event (GST_PAD_PEER (filter->sinkpad), event);
+	break;
+      default:
+	break;
+      }
+
+      break;
+    }
+  default:
+    break;
+  }
+
+  return gst_pad_event_default (pad, event);
+}
+
+static gboolean
+gst_speed_convert (GstPad * pad, GstFormat src_format, gint64 src_value,
+		   GstFormat * dest_format, gint64 * dest_value)
+{
+  gboolean res = TRUE;
+  guint scale = 1;
+  GstSpeed *filter;
+  
+  if ( src_format == *dest_format ) {
+    *dest_value = src_value;
+    return TRUE;
+  }
+
+  filter = GST_SPEED ( GST_PAD_PARENT (pad));
+
+  switch (src_format) {
+  case GST_FORMAT_BYTES:
+    switch (*dest_format) {
+    case GST_FORMAT_DEFAULT:
+      if (filter->sample_size == 0)
+	return FALSE;
+      *dest_value = src_value / filter->sample_size;
+      break;
+    case GST_FORMAT_TIME:
+      {
+	gint byterate = filter->sample_size * filter->rate;
+
+	if (byterate == 0)
+	  return FALSE;
+	*dest_value = src_value * GST_SECOND / byterate;
+	break;
+      }
+    default:
       res = FALSE;
+    }
+    break;
+  case GST_FORMAT_DEFAULT:
+    switch (*dest_format) {
+    case GST_FORMAT_BYTES:
+      *dest_value = src_value * filter->sample_size;
       break;
+    case GST_FORMAT_TIME:
+      if (filter->rate == 0)
+	return FALSE;
+      *dest_value = src_value * GST_SECOND / filter->rate;
+      break;
+    default:
+      res = FALSE;
     }
+    break;
+  case GST_FORMAT_TIME:
+    switch (*dest_format) {
+    case GST_FORMAT_BYTES:
+      scale = filter->sample_size;
+      /* fallthrough */
+    case GST_FORMAT_DEFAULT:
+      *dest_value =
+	src_value * scale * filter->rate / GST_SECOND;
+      break;
     default:
       res = FALSE;
+    }
+    break;
+  default:
+    res = FALSE;
+  }
+  return res;
+}
+
+static gboolean
+speed_src_query (GstPad * pad, GstQuery * query)
+
+{
+  gboolean res = TRUE;
+  GstSpeed *filter;
+
+  filter = GST_SPEED ( GST_PAD_PARENT (pad));
+
+  switch (GST_QUERY_TYPE (query)) {
+  case GST_QUERY_POSITION:
+    {
+      GstFormat format;
+      GstFormat rformat = GST_FORMAT_TIME;
+      gint64 cur, end;
+      GstPad *peer;
+      GstFormat conv_format = GST_FORMAT_TIME;
+
+      /* save requested format */
+      gst_query_parse_position (query, &format, NULL, NULL);
+
+      /* query peer for total length in bytes */
+      gst_query_set_position (query, GST_FORMAT_TIME, -1, -1);
+
+
+      if ((peer = gst_pad_get_peer (filter->sinkpad)) == NULL)
+        goto error;
+
+      if ( ! gst_pad_query_position (peer, &rformat, &cur, &end) ) {
+        GST_LOG_OBJECT (filter, "query on peer pad failed");
+	gst_object_unref (peer);
+        goto error;
+      }
+      gst_object_unref (peer);
+
+
+      if (rformat == GST_FORMAT_BYTES)
+        GST_LOG_OBJECT (filter, "peer pad returned total=%lld bytes",
+			end);
+      else if (rformat == GST_FORMAT_TIME)
+        GST_LOG_OBJECT (filter, "peer pad returned time=%lld", end);
+
+      /* convert to time format */
+      if ( ! gst_speed_convert (pad, rformat, cur, &conv_format, &cur) ) {
+	return FALSE;
+      }
+      /* convert to time format */
+      if ( ! gst_speed_convert (pad, rformat, end, &conv_format, &end) ) {
+	return FALSE;
+      }
+
+      /* adjust for speed factor */
+      cur /= filter->speed;
+      end /= filter->speed;
+
+      /* convert to time format */
+      if ( ! gst_speed_convert (pad, conv_format, cur, &format, &cur) ) {
+	return FALSE;
+      }
+      /* convert to time format */
+      if ( ! gst_speed_convert (pad, conv_format, end, &format, &end) ) {
+	return FALSE;
+      }
+
+      gst_query_set_position (query, format, cur, end);
+
+      GST_LOG_OBJECT (filter,
+		      "position query: peer returned total: %llu - we return %llu (format %u)",
+		      end, cur, format);
+
       break;
+    }
+  default:
+    res = FALSE;
+    break;
   }
+
   return res;
+
+ error:
+
+  GST_DEBUG ("error handling query");
+  return FALSE;
 }
 
+#if 0
+speed_src_query (GstPad * pad, GstQueryType type,
+		 GstFormat * format, gint64 * val)
+{
+  gboolean res = TRUE;
+  GstSpeed *filter;
+  
+  filter = GST_SPEED ( GST_PAD_PARENT (pad));
+  
+  switch (type) {
+  case GST_QUERY_POSITION:
+    {
+      switch (*format) {
+      case GST_FORMAT_BYTES:
+	/* fall through */
+      case GST_FORMAT_DEFAULT:
+	/* fall through */
+      case GST_FORMAT_TIME:
+        {
+          gint64 peer_value;
+          const GstFormat *peer_formats;
+	  
+	  res = FALSE;
+	  
+          peer_formats = gst_pad_get_formats (GST_PAD_PEER (filter->sinkpad));
+	  
+          while (peer_formats && *peer_formats && !res) {
+	    
+            GstFormat peer_format = *peer_formats;
+	    
+            /* do the probe */
+            if (gst_pad_query (GST_PAD_PEER (filter->sinkpad), type,
+			       &peer_format, &peer_value)) {
+              GstFormat conv_format;
+	      
+              /* convert to TIME */
+              conv_format = GST_FORMAT_TIME;
+              res = gst_pad_convert (filter->sinkpad,
+				     peer_format, peer_value, &conv_format, val);
+	      
+              /* adjust for speed factor */
+              *val = (gint64) (((gdouble) * val) / filter->speed);
+
+              /* and to final format */
+              res &= gst_pad_convert (pad, GST_FORMAT_TIME, *val, format, val);
+            }
+            peer_formats++;
+          }
+          break;
+        }
+      default:
+	res = FALSE;
+	break;
+      }
+      break;
+    }
+  default:
+    res = FALSE;
+    break;
+  }
+  return res;
+}
+#endif
+
 static void
 speed_base_init (gpointer g_class)
 {
@@ -210,9 +466,9 @@ speed_base_init (gpointer g_class)
   gst_element_class_set_details (element_class, &speed_details);
 
   gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_speed_src_template));
+				      gst_static_pad_template_get (&gst_speed_src_template));
   gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_speed_sink_template));
+				      gst_static_pad_template_get (&gst_speed_sink_template));
 }
 static void
 speed_class_init (GstSpeedClass * klass)
@@ -227,39 +483,40 @@ speed_class_init (GstSpeedClass * klass)
   parent_class = g_type_class_peek_parent (klass);
 
   g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_SPEED,
-      g_param_spec_float ("speed", "speed", "speed",
-          0.1, 40.0, 1.0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+				   g_param_spec_float ("speed", "speed", "speed",
+						       0.1, 40.0, 1.0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
 }
 
 static void
 speed_init (GstSpeed * filter)
 {
   filter->sinkpad =
-      gst_pad_new_from_template (gst_static_pad_template_get
-      (&gst_speed_sink_template), "sink");
-  gst_pad_set_setcaps_function (filter->sinkpad, gst_speed_setcaps);
+    gst_pad_new_from_template (gst_static_pad_template_get
+			       (&gst_speed_sink_template), "sink");
+  gst_pad_set_setcaps_function (filter->sinkpad, speed_setcaps);
   gst_pad_set_chain_function (filter->sinkpad, speed_chain);
-  gst_pad_set_getcaps_function (filter->sinkpad, gst_pad_proxy_getcaps);
   gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
+  gst_pad_set_event_function (filter->sinkpad, speed_sink_event);
 
   filter->srcpad =
-      gst_pad_new_from_template (gst_static_pad_template_get
-      (&gst_speed_src_template), "src");
-  /*gst_pad_set_link_function (filter->srcpad, speed_link); */
-  gst_pad_set_setcaps_function (filter->srcpad, gst_speed_setcaps);
-  gst_pad_set_getcaps_function (filter->srcpad, gst_pad_proxy_getcaps);
+    gst_pad_new_from_template (gst_static_pad_template_get
+			       (&gst_speed_src_template), "src");
+  gst_pad_set_setcaps_function (filter->srcpad, speed_setcaps);
   gst_pad_set_query_type_function (filter->srcpad, speed_get_query_types);
   gst_pad_set_query_function (filter->srcpad, speed_src_query);
   gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
 
+  gst_pad_set_event_function (filter->srcpad, speed_src_event);
+
   filter->offset = 0;
   filter->timestamp = 0;
   filter->sample_size = 0;
+
 }
 
 static inline guint
 speed_chain_int16 (GstSpeed * filter, GstBuffer * in_buf, GstBuffer * out_buf,
-    guint c, guint in_samples)
+		   guint c, guint in_samples)
 {
   gint16 *in_data, *out_data;
   gfloat interp, lower, i_float;
@@ -277,7 +534,7 @@ speed_chain_int16 (GstSpeed * filter, Gs
     interp = i_float - floor (i_float);
 
     out_data[j * filter->channels] =
-        lower * (1 - interp) + in_data[i * filter->channels] * interp;
+      lower * (1 - interp) + in_data[i * filter->channels] * interp;
 
     lower = in_data[i * filter->channels];
 
@@ -292,7 +549,7 @@ speed_chain_int16 (GstSpeed * filter, Gs
 
 static inline guint
 speed_chain_float32 (GstSpeed * filter, GstBuffer * in_buf, GstBuffer * out_buf,
-    guint c, guint in_samples)
+		     guint c, guint in_samples)
 {
   gfloat *in_data, *out_data;
   gfloat interp, lower, i_float;
@@ -310,7 +567,7 @@ speed_chain_float32 (GstSpeed * filter, 
     interp = i_float - floor (i_float);
 
     out_data[j * filter->channels] =
-        lower * (1 - interp) + in_data[i * filter->channels] * interp;
+      lower * (1 - interp) + in_data[i * filter->channels] * interp;
 
     lower = in_data[i * filter->channels];
 
@@ -323,64 +580,139 @@ speed_chain_float32 (GstSpeed * filter, 
   return j;
 }
 
+
+static gboolean speed_sink_event (GstPad * pad, GstEvent * event) {
+
+
+  GstSpeed *filter;
+  gboolean ret;
+
+  filter = GST_SPEED (GST_OBJECT_PARENT (pad));
+
+  switch (GST_EVENT_TYPE (event)) {
+  case GST_EVENT_NEWSEGMENT:
+    {
+
+      gdouble rate;
+      GstFormat format, conv_format;
+      gint64 start_value, stop_value, base;
+
+      GST_STREAM_LOCK (pad);
+
+      gst_event_parse_newsegment (event, &rate, &format, &start_value, &stop_value, &base);
+
+      g_assert (filter->speed > 0);
+
+      start_value /= filter->speed;
+      stop_value /= filter->speed;
+
+      if (format == GST_FORMAT_TIME) {
+
+	conv_format = GST_FORMAT_BYTES;
+	
+	filter->timestamp = start_value;
+	ret = gst_speed_convert (pad, GST_FORMAT_TIME, filter->timestamp, 
+				      &conv_format, &filter->offset);
+
+
+      } else if ( format == GST_FORMAT_BYTES ) {
+
+	conv_format = GST_FORMAT_TIME;
+
+	filter->offset = start_value;
+	ret = gst_speed_convert (pad, GST_FORMAT_BYTES, filter->offset, 
+				 &conv_format, &filter->timestamp);
+
+	
+      } else if ( format == GST_FORMAT_DEFAULT  ) {
+
+	conv_format = GST_FORMAT_TIME;
+
+	ret = gst_speed_convert (pad, GST_FORMAT_BYTES, start_value,
+				      &conv_format, &filter->timestamp);
+
+	conv_format = GST_FORMAT_BYTES;
+
+	ret = gst_speed_convert (pad, GST_FORMAT_TIME, start_value, 
+				      &conv_format, &filter->offset);
+
+      }
+
+      gst_event_unref (event);
+      event = gst_event_new_newsegment (rate, format, start_value, stop_value, base);	
+
+
+      if ( ! (ret = gst_pad_event_default (pad, event)) ) {
+	gst_event_unref (event);	
+      }
+
+
+      GST_STREAM_UNLOCK (pad);
+
+      return TRUE;
+
+      break;
+    }
+
+  case GST_EVENT_EOS:
+
+    GST_STREAM_LOCK (pad);
+
+    if ( ! (ret = gst_pad_event_default (pad, event)) ) {
+      gst_event_unref (event);
+    }
+
+    GST_STREAM_UNLOCK (pad);
+
+    return TRUE;
+
+    break;
+    
+  default:
+    break;
+  }
+
+  return gst_pad_event_default (pad, event);
+  
+}
+
 static GstFlowReturn
-speed_chain (GstPad * pad, GstBuffer * buf)
+speed_chain (GstPad * pad, GstBuffer * in_buf)
 {
   GstBuffer *out_buf;
   GstSpeed *filter;
   guint c, in_samples, out_samples, out_size;
   GstFlowReturn result = GST_FLOW_OK;
 
-/*
-  g_return_if_fail (pad != NULL);
-  g_return_if_fail (GST_IS_PAD (pad));
-  g_return_if_fail (data != NULL);
-*/
-  filter = GST_SPEED (GST_OBJECT_PARENT (pad));
-  /*g_return_if_fail (GST_IS_SPEED (filter)); */
+  g_return_val_if_fail (pad != NULL, GST_FLOW_ERROR);
+  g_return_val_if_fail (GST_IS_PAD (pad), GST_FLOW_ERROR);
 
-  if (GST_IS_EVENT (buf)) {
-    switch (GST_EVENT_TYPE (GST_EVENT (buf))) {
-      case GST_EVENT_NEWSEGMENT:
-      {                         /*
-                                   gint64 timestamp, offset;
-                                   GstFormat format = GST_FORMAT_UNDEFINED;
-                                   gint64 value, end_value;
-
-                                   gst_event_parse_newsegment (GST_EVENT (buf), NULL, &format, &value, &end_value, NULL);
-
-                                   if (format == GST_FORMAT_TIME) {
-                                   filter->timestamp = timestamp;
-                                   filter->offset = timestamp * filter->rate / GST_SECOND;
-                                   }
-                                   if (format == GST_FORMAT_BYTES) {
-                                   filter->offset = offset;
-                                   filter->timestamp = offset * GST_SECOND / filter->rate;
-                                   }
-                                 */
-        break;
-      }
-      default:
-        break;
-    }
-    gst_pad_event_default (pad, GST_EVENT (buf));
-    return GST_FLOW_OK;
-  }
+  filter = GST_SPEED (GST_PAD_PARENT (pad));
+
+  /* buffersize has to be aligned by samplesize */
+  out_size = ceil ((gfloat) GST_BUFFER_SIZE (in_buf) / filter->speed);
+  out_size = ((out_size + filter->sample_size - 1) / filter->sample_size ) *
+    filter->sample_size;
 
-  out_size = ceil ((gfloat) GST_BUFFER_SIZE (buf) / filter->speed);
   result =
-      gst_pad_alloc_buffer (filter->srcpad, -1, out_size,
-      GST_PAD_CAPS (filter->srcpad), &out_buf);
+    gst_pad_alloc_buffer (filter->srcpad, -1, out_size,
+			  GST_PAD_CAPS (filter->srcpad), &out_buf);
 
-  in_samples = GST_BUFFER_SIZE (buf) / filter->sample_size;
+  if ( result != GST_FLOW_OK ) {
+    gst_buffer_unref (in_buf);
+    return result;
+  }
+
+  in_samples = GST_BUFFER_SIZE (in_buf) / filter->sample_size;
 
   out_samples = 0;
 
   for (c = 0; c < filter->channels; ++c) {
     if (filter->format == GST_SPEED_FORMAT_INT) {
-      out_samples = speed_chain_int16 (filter, buf, out_buf, c, in_samples);
+      out_samples = speed_chain_int16 (filter, in_buf, out_buf, c, in_samples);
     } else {
-      out_samples = speed_chain_float32 (filter, buf, out_buf, c, in_samples);
+      out_samples =
+	speed_chain_float32 (filter, in_buf, out_buf, c, in_samples);
     }
   }
 
@@ -393,46 +725,48 @@ speed_chain (GstPad * pad, GstBuffer * b
   filter->timestamp = filter->offset * GST_SECOND / filter->rate;
 
   GST_BUFFER_DURATION (out_buf) =
-      filter->timestamp - GST_BUFFER_TIMESTAMP (out_buf);
+    filter->timestamp - GST_BUFFER_TIMESTAMP (out_buf);
 
   gst_pad_push (filter->srcpad, out_buf);
 
-  return result;
-  /*gst_buffer_unref (in_buf); */
+  gst_buffer_unref (in_buf);
+  return GST_FLOW_OK;
+
 }
 
 static void
 speed_set_property (GObject * object, guint prop_id, const GValue * value,
-    GParamSpec * pspec)
+		    GParamSpec * pspec)
 {
   GstSpeed *filter = (GstSpeed *) object;
 
   g_return_if_fail (GST_IS_SPEED (object));
 
   switch (prop_id) {
-    case ARG_SPEED:
-      filter->speed = g_value_get_float (value);
-      break;
-    default:
-      break;
+  case ARG_SPEED:
+    filter->speed = g_value_get_float (value);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+    break;
   }
 }
 
 static void
 speed_get_property (GObject * object, guint prop_id, GValue * value,
-    GParamSpec * pspec)
+		    GParamSpec * pspec)
 {
   GstSpeed *filter = (GstSpeed *) object;
 
   g_return_if_fail (GST_IS_SPEED (object));
 
   switch (prop_id) {
-    case ARG_SPEED:
-      g_value_set_float (value, filter->speed);
-      break;
-    default:
-      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-      break;
+  case ARG_SPEED:
+    g_value_set_float (value, filter->speed);
+    break;
+  default:
+    G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    break;
   }
 }
 
@@ -442,15 +776,12 @@ speed_change_state (GstElement * element
   GstSpeed *speed = GST_SPEED (element);
 
   switch (transition) {
-    case GST_STATE_CHANGE_PAUSED_TO_READY:
-      break;
-    case GST_STATE_CHANGE_READY_TO_PAUSED:
-      speed->offset = 0;
-      speed->timestamp = 0;
-      speed->sample_size = 0;
-      break;
-    default:
-      break;
+  case GST_STATE_CHANGE_READY_TO_PAUSED:
+    speed->offset = 0;
+    speed->timestamp = 0;
+    break;
+  default:
+    break;
   }
 
   if (GST_ELEMENT_CLASS (parent_class)->change_state)
@@ -466,7 +797,7 @@ plugin_init (GstPlugin * plugin)
 }
 
 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
-    GST_VERSION_MINOR,
-    "speed",
-    "Set speed/pitch on audio/raw streams (resampler)",
-    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
+		   GST_VERSION_MINOR,
+		   "speed",
+		   "Set speed/pitch on audio/raw streams (resampler)",
+		   plugin_init, VERSION, GST_LICENSE, GST_PACKAGE, GST_ORIGIN)
Index: gstspeed.h
===================================================================
RCS file: /cvs/gstreamer/gst-plugins-bad/gst/speed/gstspeed.h,v
retrieving revision 1.10
diff -u -p -r1.10 gstspeed.h
--- gstspeed.h	10 Feb 2005 15:06:13 -0000	1.10
+++ gstspeed.h	7 Oct 2005 19:28:00 -0000
@@ -60,7 +60,6 @@ struct _GstSpeed {
   guint          rate;
   guint          channels;
   guint          width;
-  guint          buffer_frames;
 
   guint          sample_size;
   GstSpeedFormat format;
