Merge branch 'tizen' into tizen_gst_1.19.2
[platform/upstream/gstreamer.git] / ext / soundtouch / gstpitch.cc
index 6b5b95f..ca8058d 100644 (file)
 #undef PACKAGE_BUGREPORT
 #undef PACKAGE
 
-#define FLOAT_SAMPLES 1
 #include <soundtouch/SoundTouch.h>
 
 #include <gst/gst.h>
-#include <gst/controller/gstcontroller.h>
+#include <gst/audio/audio.h>
+
 #include "gstpitch.hh"
 #include <math.h>
 
@@ -61,26 +61,40 @@ enum
   ARG_PITCH
 };
 
-#define SUPPORTED_CAPS \
-GST_STATIC_CAPS( \
-  "audio/x-raw-float, " \
-    "rate = (int) [ 8000, MAX ], " \
-    "channels = (int) [ 1, 2 ], " \
-    "endianness = (int) BYTE_ORDER, " \
-    "width = (int) 32" \
-)
+/* For soundtouch 1.4 */
+#if defined(INTEGER_SAMPLES)
+#define SOUNDTOUCH_INTEGER_SAMPLES 1
+#elif defined(FLOAT_SAMPLES)
+#define SOUNDTOUCH_FLOAT_SAMPLES 1
+#endif
+
+#if defined(SOUNDTOUCH_FLOAT_SAMPLES)
+  #define SUPPORTED_CAPS \
+    "audio/x-raw, " \
+      "format = (string) " GST_AUDIO_NE (F32) ", " \
+      "rate = (int) [ 8000, MAX ], " \
+      "channels = (int) [ 1, MAX ]"
+#elif defined(SOUNDTOUCH_INTEGER_SAMPLES)
+  #define SUPPORTED_CAPS \
+    "audio/x-raw, " \
+      "format = (string) " GST_AUDIO_NE (S16) ", " \
+      "rate = (int) [ 8000, MAX ], " \
+      "channels = (int) [ 1, MAX ]"
+#else
+#error "Only integer or float samples are supported"
+#endif
 
 static GstStaticPadTemplate gst_pitch_sink_template =
 GST_STATIC_PAD_TEMPLATE ("sink",
     GST_PAD_SINK,
     GST_PAD_ALWAYS,
-    SUPPORTED_CAPS);
+    GST_STATIC_CAPS (SUPPORTED_CAPS));
 
 static GstStaticPadTemplate gst_pitch_src_template =
 GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    SUPPORTED_CAPS);
+    GST_STATIC_CAPS (SUPPORTED_CAPS));
 
 static void gst_pitch_dispose (GObject * object);
 static void gst_pitch_set_property (GObject * object,
@@ -89,32 +103,23 @@ static void gst_pitch_get_property (GObject * object,
     guint prop_id, GValue * value, GParamSpec * pspec);
 
 
-static gboolean gst_pitch_sink_setcaps (GstPad * pad, GstCaps * caps);
-static GstFlowReturn gst_pitch_chain (GstPad * pad, GstBuffer * buffer);
+static gboolean gst_pitch_setcaps (GstPitch * pitch, GstCaps * caps);
+static GstFlowReturn gst_pitch_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer);
 static GstStateChangeReturn gst_pitch_change_state (GstElement * element,
     GstStateChange transition);
-static gboolean gst_pitch_sink_event (GstPad * pad, GstEvent * event);
-static gboolean gst_pitch_src_event (GstPad * pad, GstEvent * event);
-
-static gboolean gst_pitch_src_query (GstPad * pad, GstQuery * query);
-static const GstQueryType *gst_pitch_get_query_types (GstPad * pad);
-
-GST_BOILERPLATE (GstPitch, gst_pitch, GstElement, GST_TYPE_ELEMENT);
-
-static void
-gst_pitch_base_init (gpointer g_class)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+static gboolean gst_pitch_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_pitch_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
 
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_pitch_src_template));
-  gst_element_class_add_pad_template (gstelement_class,
-      gst_static_pad_template_get (&gst_pitch_sink_template));
+static gboolean gst_pitch_src_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 
-  gst_element_class_set_details_simple (gstelement_class, "Pitch controller",
-      "Filter/Converter/Audio", "Control the pitch of an audio stream",
-      "Wouter Paesen <wouter@blue-gate.be>");
-}
+#define gst_pitch_parent_class parent_class
+G_DEFINE_TYPE_WITH_PRIVATE (GstPitch, gst_pitch, GST_TYPE_ELEMENT);
+GST_ELEMENT_REGISTER_DEFINE (pitch, "pitch", GST_RANK_NONE,
+    GST_TYPE_PITCH);
 
 static void
 gst_pitch_class_init (GstPitchClass * klass)
@@ -131,36 +136,45 @@ gst_pitch_class_init (GstPitchClass * klass)
   gobject_class->set_property = gst_pitch_set_property;
   gobject_class->get_property = gst_pitch_get_property;
   gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pitch_dispose);
-  element_class->change_state = GST_DEBUG_FUNCPTR (gst_pitch_change_state);
 
   g_object_class_install_property (gobject_class, ARG_PITCH,
       g_param_spec_float ("pitch", "Pitch",
           "Audio stream pitch", 0.1, 10.0, 1.0,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)));
+          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
+              G_PARAM_STATIC_STRINGS)));
 
   g_object_class_install_property (gobject_class, ARG_TEMPO,
       g_param_spec_float ("tempo", "Tempo",
           "Audio stream tempo", 0.1, 10.0, 1.0,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)));
+          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
+              G_PARAM_STATIC_STRINGS)));
 
   g_object_class_install_property (gobject_class, ARG_RATE,
       g_param_spec_float ("rate", "Rate",
           "Audio stream rate", 0.1, 10.0, 1.0,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)));
+          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
+              G_PARAM_STATIC_STRINGS)));
 
   g_object_class_install_property (gobject_class, ARG_OUT_RATE,
       g_param_spec_float ("output-rate", "Output Rate",
           "Output rate on downstream segment events", 0.1, 10.0, 1.0,
-          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE | G_PARAM_STATIC_STRINGS)));
+          (GParamFlags) (G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE |
+              G_PARAM_STATIC_STRINGS)));
 
-  g_type_class_add_private (gobject_class, sizeof (GstPitchPrivate));
+  element_class->change_state = GST_DEBUG_FUNCPTR (gst_pitch_change_state);
+
+  gst_element_class_add_static_pad_template (element_class, &gst_pitch_src_template);
+  gst_element_class_add_static_pad_template (element_class, &gst_pitch_sink_template);
+
+  gst_element_class_set_static_metadata (element_class, "Pitch controller",
+      "Filter/Effect/Audio", "Control the pitch of an audio stream",
+      "Wouter Paesen <wouter@blue-gate.be>");
 }
 
 static void
-gst_pitch_init (GstPitch * pitch, GstPitchClass * pitch_class)
+gst_pitch_init (GstPitch * pitch)
 {
-  pitch->priv =
-      G_TYPE_INSTANCE_GET_PRIVATE ((pitch), GST_TYPE_PITCH, GstPitchPrivate);
+  pitch->priv = (GstPitchPrivate *) gst_pitch_get_instance_private (pitch);
 
   pitch->sinkpad =
       gst_pad_new_from_static_template (&gst_pitch_sink_template, "sink");
@@ -168,24 +182,16 @@ gst_pitch_init (GstPitch * pitch, GstPitchClass * pitch_class)
       GST_DEBUG_FUNCPTR (gst_pitch_chain));
   gst_pad_set_event_function (pitch->sinkpad,
       GST_DEBUG_FUNCPTR (gst_pitch_sink_event));
-  gst_pad_set_setcaps_function (pitch->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_pitch_sink_setcaps));
-  gst_pad_set_getcaps_function (pitch->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
+  GST_PAD_SET_PROXY_CAPS (pitch->sinkpad);
   gst_element_add_pad (GST_ELEMENT (pitch), pitch->sinkpad);
 
   pitch->srcpad =
       gst_pad_new_from_static_template (&gst_pitch_src_template, "src");
   gst_pad_set_event_function (pitch->srcpad,
       GST_DEBUG_FUNCPTR (gst_pitch_src_event));
-  gst_pad_set_query_type_function (pitch->srcpad,
-      GST_DEBUG_FUNCPTR (gst_pitch_get_query_types));
   gst_pad_set_query_function (pitch->srcpad,
       GST_DEBUG_FUNCPTR (gst_pitch_src_query));
-  gst_pad_set_setcaps_function (pitch->srcpad,
-      GST_DEBUG_FUNCPTR (gst_pitch_sink_setcaps));
-  gst_pad_set_getcaps_function (pitch->srcpad,
-      GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
+  GST_PAD_SET_PROXY_CAPS (pitch->sinkpad);
   gst_element_add_pad (GST_ELEMENT (pitch), pitch->srcpad);
 
   pitch->priv->st = new soundtouch::SoundTouch ();
@@ -195,7 +201,7 @@ gst_pitch_init (GstPitch * pitch, GstPitchClass * pitch_class)
   pitch->out_seg_rate = 1.0;
   pitch->seg_arate = 1.0;
   pitch->pitch = 1.0;
-  pitch->next_buffer_time = 0;
+  pitch->next_buffer_time = GST_CLOCK_TIME_NONE;
   pitch->next_buffer_offset = 0;
 
   pitch->priv->st->setRate (pitch->rate);
@@ -226,7 +232,7 @@ gst_pitch_update_duration (GstPitch * pitch)
 {
   GstMessage *m;
 
-  m = gst_message_new_duration (GST_OBJECT (pitch), GST_FORMAT_TIME, -1);
+  m = gst_message_new_duration_changed (GST_OBJECT (pitch));
   gst_element_post_message (GST_ELEMENT (pitch), m);
 }
 
@@ -240,14 +246,16 @@ gst_pitch_set_property (GObject * object, guint prop_id,
   switch (prop_id) {
     case ARG_TEMPO:
       pitch->tempo = g_value_get_float (value);
-      pitch->priv->stream_time_ratio = pitch->tempo * pitch->rate * pitch->seg_arate;
+      pitch->priv->stream_time_ratio =
+          pitch->tempo * pitch->rate * pitch->seg_arate;
       pitch->priv->st->setTempo (pitch->tempo * pitch->seg_arate);
       GST_OBJECT_UNLOCK (pitch);
       gst_pitch_update_duration (pitch);
       break;
     case ARG_RATE:
       pitch->rate = g_value_get_float (value);
-      pitch->priv->stream_time_ratio = pitch->tempo * pitch->rate * pitch->seg_arate;
+      pitch->priv->stream_time_ratio =
+          pitch->tempo * pitch->rate * pitch->seg_arate;
       pitch->priv->st->setRate (pitch->rate);
       GST_OBJECT_UNLOCK (pitch);
       gst_pitch_update_duration (pitch);
@@ -256,6 +264,7 @@ gst_pitch_set_property (GObject * object, guint prop_id,
       /* Has no effect until the next input segment */
       pitch->out_seg_rate = g_value_get_float (value);
       GST_OBJECT_UNLOCK (pitch);
+      break;
     case ARG_PITCH:
       pitch->pitch = g_value_get_float (value);
       pitch->priv->st->setPitch (pitch->pitch);
@@ -296,40 +305,20 @@ gst_pitch_get_property (GObject * object, guint prop_id,
 }
 
 static gboolean
-gst_pitch_sink_setcaps (GstPad * pad, GstCaps * caps)
+gst_pitch_setcaps (GstPitch * pitch, GstCaps * caps)
 {
-  GstPitch *pitch;
   GstPitchPrivate *priv;
-  GstStructure *structure;
-  GstPad *otherpad;
-  gint rate, channels;
 
-  pitch = GST_PITCH (GST_PAD_PARENT (pad));
   priv = GST_PITCH_GET_PRIVATE (pitch);
 
-  otherpad = (pad == pitch->srcpad) ? pitch->sinkpad : pitch->srcpad;
-
-  if (!gst_pad_set_caps (otherpad, caps))
-    return FALSE;
-
-  structure = gst_caps_get_structure (caps, 0);
-
-  if (!gst_structure_get_int (structure, "rate", &rate) ||
-      !gst_structure_get_int (structure, "channels", &channels)) {
+  if (!gst_audio_info_from_caps (&pitch->info, caps))
     return FALSE;
-  }
 
   GST_OBJECT_LOCK (pitch);
 
-  pitch->samplerate = rate;
-  pitch->channels = channels;
-
   /* notify the soundtouch instance of this change */
-  priv->st->setSampleRate (rate);
-  priv->st->setChannels (channels);
-
-  /* calculate sample size */
-  pitch->sample_size = (sizeof (gfloat) * channels);
+  priv->st->setSampleRate (pitch->info.rate);
+  priv->st->setChannels (pitch->info.channels);
 
   GST_OBJECT_UNLOCK (pitch);
 
@@ -364,6 +353,7 @@ gst_pitch_prepare_buffer (GstPitch * pitch)
   GstPitchPrivate *priv;
   guint samples;
   GstBuffer *buffer;
+  GstMapInfo info;
 
   priv = GST_PITCH_GET_PRIVATE (pitch);
 
@@ -373,15 +363,11 @@ gst_pitch_prepare_buffer (GstPitch * pitch)
   if (samples == 0)
     return NULL;
 
-  if (gst_pad_alloc_buffer_and_set_caps (pitch->srcpad, GST_BUFFER_OFFSET_NONE,
-          samples * pitch->sample_size, GST_PAD_CAPS (pitch->srcpad), &buffer)
-      != GST_FLOW_OK) {
-    buffer = gst_buffer_new_and_alloc (samples * pitch->sample_size);
-    gst_buffer_set_caps (buffer, GST_PAD_CAPS (pitch->srcpad));
-  }
+  buffer = gst_buffer_new_and_alloc (samples * pitch->info.bpf);
 
-  samples =
-      priv->st->receiveSamples ((gfloat *) GST_BUFFER_DATA (buffer), samples);
+  gst_buffer_map (buffer, &info, (GstMapFlags) GST_MAP_READWRITE);
+  samples = priv->st->receiveSamples ((soundtouch::SAMPLETYPE *) info.data, samples);
+  gst_buffer_unmap (buffer, &info);
 
   if (samples <= 0) {
     gst_buffer_unref (buffer);
@@ -389,7 +375,7 @@ gst_pitch_prepare_buffer (GstPitch * pitch)
   }
 
   GST_BUFFER_DURATION (buffer) =
-      gst_util_uint64_scale (samples, GST_SECOND, pitch->samplerate);
+      gst_util_uint64_scale (samples, GST_SECOND, pitch->info.rate);
   /* temporary store samples here, to avoid having to recalculate this */
   GST_BUFFER_OFFSET (buffer) = (gint64) samples;
 
@@ -404,12 +390,11 @@ gst_pitch_flush_buffer (GstPitch * pitch, gboolean send)
 {
   GstBuffer *buffer;
 
-  GST_DEBUG_OBJECT (pitch, "flushing buffer");
-
-  if (pitch->next_buffer_offset == 0)
-    return GST_FLOW_OK;
+  if (pitch->priv->st->numUnprocessedSamples() != 0) {
+    GST_DEBUG_OBJECT (pitch, "flushing buffer");
+    pitch->priv->st->flush ();
+  }
 
-  pitch->priv->st->flush ();
   if (!send)
     return GST_FLOW_OK;
 
@@ -422,12 +407,12 @@ gst_pitch_flush_buffer (GstPitch * pitch, gboolean send)
 }
 
 static gboolean
-gst_pitch_src_event (GstPad * pad, GstEvent * event)
+gst_pitch_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstPitch *pitch;
   gboolean res;
 
-  pitch = GST_PITCH (gst_pad_get_parent (pad));
+  pitch = GST_PITCH (parent);
 
   GST_DEBUG_OBJECT (pad, "received %s event", GST_EVENT_TYPE_NAME (event));
 
@@ -440,6 +425,7 @@ gst_pitch_src_event (GstPad * pad, GstEvent * event)
       GstSeekType cur_type, stop_type;
       gint64 cur, stop;
       gfloat stream_time_ratio;
+      guint32 seqnum;
 
       GST_OBJECT_LOCK (pitch);
       stream_time_ratio = pitch->priv->stream_time_ratio;
@@ -448,6 +434,8 @@ gst_pitch_src_event (GstPad * pad, GstEvent * event)
       gst_event_parse_seek (event, &rate, &format, &flags,
           &cur_type, &cur, &stop_type, &stop);
 
+      seqnum = gst_event_get_seqnum (event);
+
       gst_event_unref (event);
 
       if (format == GST_FORMAT_TIME || format == GST_FORMAT_DEFAULT) {
@@ -457,26 +445,24 @@ gst_pitch_src_event (GstPad * pad, GstEvent * event)
 
         event = gst_event_new_seek (rate, format, flags,
             cur_type, cur, stop_type, stop);
-        res = gst_pad_event_default (pad, event);
+        gst_event_set_seqnum (event, seqnum);
+        res = gst_pad_event_default (pad, parent, event);
       } else {
         GST_WARNING_OBJECT (pitch,
             "Seeking only supported in TIME or DEFAULT format");
         res = FALSE;
       }
-
       break;
     }
     default:
-      res = gst_pad_event_default (pad, event);
+      res = gst_pad_event_default (pad, parent, event);
       break;
   }
-
-  gst_object_unref (pitch);
   return res;
 }
 
-/* generic convert function based on caps, no rate 
- * used here 
+/* generic convert function based on caps, no rate
+ * used here
  */
 static gboolean
 gst_pitch_convert (GstPitch * pitch,
@@ -490,8 +476,8 @@ gst_pitch_convert (GstPitch * pitch,
   g_return_val_if_fail (dst_format && dst_value, FALSE);
 
   GST_OBJECT_LOCK (pitch);
-  sample_size = pitch->sample_size;
-  samplerate = pitch->samplerate;
+  sample_size = pitch->info.bpf;
+  samplerate = pitch->info.rate;
   GST_OBJECT_UNLOCK (pitch);
 
   if (sample_size == 0 || samplerate == 0) {
@@ -557,22 +543,8 @@ gst_pitch_convert (GstPitch * pitch,
   return res;
 }
 
-static const GstQueryType *
-gst_pitch_get_query_types (GstPad * pad)
-{
-  static const GstQueryType types[] = {
-    GST_QUERY_POSITION,
-    GST_QUERY_DURATION,
-    GST_QUERY_CONVERT,
-    GST_QUERY_LATENCY,
-    GST_QUERY_NONE
-  };
-
-  return types;
-}
-
 static gboolean
-gst_pitch_src_query (GstPad * pad, GstQuery * query)
+gst_pitch_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
   GstPitch *pitch;
   gboolean res = FALSE;
@@ -580,8 +552,10 @@ gst_pitch_src_query (GstPad * pad, GstQuery * query)
   gint64 next_buffer_offset;
   GstClockTime next_buffer_time;
 
-  pitch = GST_PITCH (gst_pad_get_parent (pad));
+  pitch = GST_PITCH (parent);
+
   GST_LOG ("%s query", GST_QUERY_TYPE_NAME (query));
+
   GST_OBJECT_LOCK (pitch);
   stream_time_ratio = pitch->priv->stream_time_ratio;
   next_buffer_time = pitch->next_buffer_time;
@@ -593,7 +567,7 @@ gst_pitch_src_query (GstPad * pad, GstQuery * query)
       GstFormat format;
       gint64 duration;
 
-      if (!gst_pad_query_default (pad, query)) {
+      if (!gst_pad_query_default (pad, parent, query)) {
         GST_DEBUG_OBJECT (pitch, "upstream provided no duration");
         break;
       }
@@ -676,8 +650,6 @@ gst_pitch_src_query (GstPad * pad, GstQuery * query)
           min += pitch->min_latency;
           if (max != GST_CLOCK_TIME_NONE)
             max += pitch->max_latency;
-          else
-            max = pitch->max_latency;
 
           GST_DEBUG ("Calculated total latency : min %"
               GST_TIME_FORMAT " max %" GST_TIME_FORMAT,
@@ -689,29 +661,26 @@ gst_pitch_src_query (GstPad * pad, GstQuery * query)
       break;
     }
     default:
-      res = gst_pad_query_default (pad, query);
+      res = gst_pad_query_default (pad, parent, query);
       break;
   }
 
-  gst_object_unref (pitch);
   return res;
 }
 
 /* this function returns FALSE if not enough data is known to transform the
  * segment into proper downstream values.  If the function does return false
- * the sgement should be stalled until enough information is available.
- * If the funtion returns TRUE, event will be replaced by the new downstream
+ * the segment should be stalled until enough information is available.
+ * If the function returns TRUE, event will be replaced by the new downstream
  * compatible event.
  */
 static gboolean
 gst_pitch_process_segment (GstPitch * pitch, GstEvent ** event)
 {
-  GstFormat format, conv_format;
-  gint64 start_value, stop_value, base;
-  gint64 next_offset = 0, next_time = 0;
-  gboolean update = FALSE;
-  gdouble rate, out_seg_rate, arate, our_arate;
+  gint seqnum;
+  gdouble out_seg_rate, our_arate;
   gfloat stream_time_ratio;
+  GstSegment seg;
 
   g_return_val_if_fail (event, FALSE);
 
@@ -720,30 +689,25 @@ gst_pitch_process_segment (GstPitch * pitch, GstEvent ** event)
   out_seg_rate = pitch->out_seg_rate;
   GST_OBJECT_UNLOCK (pitch);
 
-  gst_event_parse_new_segment_full (*event, &update, &rate, &arate, &format, &start_value,
-      &stop_value, &base);
+  gst_event_copy_segment (*event, &seg);
 
-  if (format != GST_FORMAT_TIME && format != GST_FORMAT_DEFAULT) {
+  if (seg.format != GST_FORMAT_TIME && seg.format != GST_FORMAT_DEFAULT) {
     GST_WARNING_OBJECT (pitch,
         "Only NEWSEGMENT in TIME or DEFAULT format supported, sending"
         "open ended NEWSEGMENT in TIME format.");
-    gst_event_unref (*event);
-    *event =
-        gst_event_new_new_segment_full (update, rate, arate, GST_FORMAT_TIME, 0, -1, 0);
-    start_value = 0;
-    stop_value = -1;
-    base = 0;
+    seg.format = GST_FORMAT_TIME;
+    seg.start = 0;
+    seg.stop = -1;
+    seg.time = 0;
   }
 
   /* Figure out how much of the incoming 'rate' we'll apply ourselves */
-  our_arate = rate / out_seg_rate;
+  our_arate = seg.rate / out_seg_rate;
   /* update the output rate variables */
-  rate = out_seg_rate;
-  arate *= our_arate;
+  seg.rate = out_seg_rate;
+  seg.applied_rate *= our_arate;
 
-  GST_LOG_OBJECT (pitch->sinkpad,
-      "segment %" G_GINT64_FORMAT " - %" G_GINT64_FORMAT " (%d)", start_value,
-      stop_value, format);
+  GST_LOG_OBJECT (pitch->sinkpad, "in segment %" GST_SEGMENT_FORMAT, &seg);
 
   stream_time_ratio = pitch->tempo * pitch->rate * pitch->seg_arate;
 
@@ -759,43 +723,29 @@ gst_pitch_process_segment (GstPitch * pitch, GstEvent ** event)
   pitch->priv->st->setTempo (pitch->tempo * pitch->seg_arate);
   GST_OBJECT_UNLOCK (pitch);
 
-  start_value = (gint64) (start_value / stream_time_ratio);
-  if (stop_value != -1)
-    stop_value = (gint64) (stop_value / stream_time_ratio);
-  base = (gint64) (base / stream_time_ratio);
+  seg.start = (gint64) (seg.start / stream_time_ratio);
+  seg.position = (gint64) (seg.position / stream_time_ratio);
+  if (seg.stop != (guint64) - 1)
+    seg.stop = (gint64) (seg.stop / stream_time_ratio);
+  seg.time = (gint64) (seg.time / stream_time_ratio);
 
-  conv_format = GST_FORMAT_TIME;
-  if (!gst_pitch_convert (pitch, format, start_value, &conv_format, &next_time)) {
-    GST_LOG_OBJECT (pitch->sinkpad,
-        "could not convert segment start value to time");
-    return FALSE;
-  }
-
-  conv_format = GST_FORMAT_DEFAULT;
-  if (!gst_pitch_convert (pitch, format, start_value, &conv_format,
-          &next_offset)) {
-    GST_LOG_OBJECT (pitch->sinkpad,
-        "could not convert segment start value to offset");
-    return FALSE;
-  }
-
-  pitch->next_buffer_time = next_time;
-  pitch->next_buffer_offset = next_offset;
+  GST_LOG_OBJECT (pitch->sinkpad, "out segment %" GST_SEGMENT_FORMAT, &seg);
 
+  seqnum = gst_event_get_seqnum (*event);
   gst_event_unref (*event);
-  *event = gst_event_new_new_segment_full (update, rate, arate, format,
-       start_value, stop_value, base);
+  *event = gst_event_new_segment (&seg);
+  gst_event_set_seqnum (*event, seqnum);
 
   return TRUE;
 }
 
 static gboolean
-gst_pitch_sink_event (GstPad * pad, GstEvent * event)
+gst_pitch_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   gboolean res = TRUE;
   GstPitch *pitch;
 
-  pitch = GST_PITCH (gst_pad_get_parent (pad));
+  pitch = GST_PITCH (parent);
 
   GST_LOG_OBJECT (pad, "received %s event", GST_EVENT_TYPE_NAME (event));
 
@@ -804,7 +754,7 @@ gst_pitch_sink_event (GstPad * pad, GstEvent * event)
       gst_pitch_flush_buffer (pitch, FALSE);
       pitch->priv->st->clear ();
       pitch->next_buffer_offset = 0;
-      pitch->next_buffer_time = 0;
+      pitch->next_buffer_time = GST_CLOCK_TIME_NONE;
       pitch->min_latency = pitch->max_latency = 0;
       break;
     case GST_EVENT_EOS:
@@ -812,7 +762,7 @@ gst_pitch_sink_event (GstPad * pad, GstEvent * event)
       pitch->priv->st->clear ();
       pitch->min_latency = pitch->max_latency = 0;
       break;
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
       if (!gst_pitch_process_segment (pitch, &event)) {
         GST_LOG_OBJECT (pad, "not enough data known, stalling segment");
         if (GST_PITCH_GET_PRIVATE (pitch)->pending_segment)
@@ -823,15 +773,26 @@ gst_pitch_sink_event (GstPad * pad, GstEvent * event)
       pitch->priv->st->clear ();
       pitch->min_latency = pitch->max_latency = 0;
       break;
+    case GST_EVENT_CAPS:
+    {
+      GstCaps *caps;
+
+      gst_event_parse_caps (event, &caps);
+      res = gst_pitch_setcaps (pitch, caps);
+      if (!res) {
+        gst_event_unref (event);
+        goto done;
+      }
+    }
     default:
       break;
   }
 
   /* and forward it */
   if (event)
-    res = gst_pad_event_default (pad, event);
+    res = gst_pad_event_default (pad, parent, event);
 
-  gst_object_unref (pitch);
+done:
   return res;
 }
 
@@ -862,22 +823,38 @@ gst_pitch_update_latency (GstPitch * pitch, GstClockTime timestamp)
 }
 
 static GstFlowReturn
-gst_pitch_chain (GstPad * pad, GstBuffer * buffer)
+gst_pitch_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstPitch *pitch;
   GstPitchPrivate *priv;
   GstClockTime timestamp;
+  GstMapInfo info;
 
-  pitch = GST_PITCH (GST_PAD_PARENT (pad));
+  pitch = GST_PITCH (parent);
   priv = GST_PITCH_GET_PRIVATE (pitch);
 
-  gst_object_sync_values (G_OBJECT (pitch), pitch->next_buffer_time);
-
   timestamp = GST_BUFFER_TIMESTAMP (buffer);
 
+  // Remember the first time and corresponding offset
+  if (!GST_CLOCK_TIME_IS_VALID (pitch->next_buffer_time)) {
+    gfloat stream_time_ratio;
+    GstFormat out_format = GST_FORMAT_DEFAULT;
+
+    GST_OBJECT_LOCK (pitch);
+    stream_time_ratio = priv->stream_time_ratio;
+    GST_OBJECT_UNLOCK (pitch);
+
+    pitch->next_buffer_time = timestamp / stream_time_ratio;
+    gst_pitch_convert (pitch, GST_FORMAT_TIME, timestamp, &out_format,
+        &pitch->next_buffer_offset);
+  }
+
+  gst_object_sync_values (GST_OBJECT (pitch), pitch->next_buffer_time);
+
   /* push the received samples on the soundtouch buffer */
-  GST_LOG_OBJECT (pitch, "incoming buffer (%d samples)",
-      (gint) (GST_BUFFER_SIZE (buffer) / pitch->sample_size));
+  GST_LOG_OBJECT (pitch, "incoming buffer (%d samples) %" GST_TIME_FORMAT,
+      (gint) (gst_buffer_get_size (buffer) / pitch->info.bpf),
+      GST_TIME_ARGS (timestamp));
 
   if (GST_PITCH_GET_PRIVATE (pitch)->pending_segment) {
     GstEvent *event =
@@ -885,11 +862,13 @@ gst_pitch_chain (GstPad * pad, GstBuffer * buffer)
 
     GST_LOG_OBJECT (pitch, "processing stalled segment");
     if (!gst_pitch_process_segment (pitch, &event)) {
+      gst_buffer_unref (buffer);
       gst_event_unref (event);
       return GST_FLOW_ERROR;
     }
 
-    if (!gst_pad_event_default (pitch->sinkpad, event)) {
+    if (!gst_pad_event_default (pitch->sinkpad, parent, event)) {
+      gst_buffer_unref (buffer);
       gst_event_unref (event);
       return GST_FLOW_ERROR;
     }
@@ -898,21 +877,33 @@ gst_pitch_chain (GstPad * pad, GstBuffer * buffer)
     GST_PITCH_GET_PRIVATE (pitch)->pending_segment = NULL;
   }
 
-  priv->st->putSamples ((gfloat *) GST_BUFFER_DATA (buffer),
-      GST_BUFFER_SIZE (buffer) / pitch->sample_size);
+  gst_buffer_map (buffer, &info, GST_MAP_READ);
+  GST_OBJECT_LOCK (pitch);
+  priv->st->putSamples ((soundtouch::SAMPLETYPE *) info.data, info.size / pitch->info.bpf);
+  GST_OBJECT_UNLOCK (pitch);
+  gst_buffer_unmap (buffer, &info);
   gst_buffer_unref (buffer);
 
   /* Calculate latency */
 
   gst_pitch_update_latency (pitch, timestamp);
-
   /* and try to extract some samples from the soundtouch buffer */
   if (!priv->st->isEmpty ()) {
     GstBuffer *out_buffer;
 
     out_buffer = gst_pitch_prepare_buffer (pitch);
-    if (out_buffer)
+
+    if (out_buffer) {
+#ifdef TIZEN_FEATURE_PITCH_AUDIO_META
+      gint samples =  GST_BUFFER_OFFSET (out_buffer);
+
+      if (GST_AUDIO_INFO_LAYOUT (&pitch->info) ==
+          GST_AUDIO_LAYOUT_NON_INTERLEAVED) {
+        gst_buffer_add_audio_meta (out_buffer, &pitch->info, samples, NULL);
+      }
+#endif
       return gst_pitch_forward_buffer (pitch, out_buffer);
+    }
   }
 
   return GST_FLOW_OK;
@@ -928,7 +919,7 @@ gst_pitch_change_state (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_NULL_TO_READY:
       break;
     case GST_STATE_CHANGE_READY_TO_PAUSED:
-      pitch->next_buffer_time = 0;
+      pitch->next_buffer_time = GST_CLOCK_TIME_NONE;
       pitch->next_buffer_offset = 0;
       pitch->priv->st->clear ();
       pitch->min_latency = pitch->max_latency = 0;
@@ -939,7 +930,7 @@ gst_pitch_change_state (GstElement * element, GstStateChange transition)
       break;
   }
 
-  ret = parent_class->change_state (element, transition);
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
   if (ret != GST_STATE_CHANGE_SUCCESS)
     return ret;