Merge remote-tracking branch 'origin/master' into 0.11
[platform/upstream/gstreamer.git] / gst-libs / gst / audio / gstaudiodecoder.c
index ced5419..eec58b9 100644 (file)
@@ -280,25 +280,54 @@ static GstFlowReturn gst_audio_decoder_chain_reverse (GstAudioDecoder *
 
 static GstStateChangeReturn gst_audio_decoder_change_state (GstElement *
     element, GstStateChange transition);
-static gboolean gst_audio_decoder_sink_event (GstPad * pad, GstEvent * event);
-static gboolean gst_audio_decoder_src_event (GstPad * pad, GstEvent * event);
-static gboolean gst_audio_decoder_sink_setcaps (GstPad * pad, GstCaps * caps);
-static gboolean gst_audio_decoder_src_setcaps (GstPad * pad, GstCaps * caps);
-static GstFlowReturn gst_audio_decoder_chain (GstPad * pad, GstBuffer * buf);
-static gboolean gst_audio_decoder_src_query (GstPad * pad, GstQuery * query);
-static gboolean gst_audio_decoder_sink_query (GstPad * pad, GstQuery * query);
-static const GstQueryType *gst_audio_decoder_get_query_types (GstPad * pad);
+static gboolean gst_audio_decoder_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_audio_decoder_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_audio_decoder_sink_setcaps (GstAudioDecoder * dec,
+    GstCaps * caps);
+gboolean gst_audio_decoder_src_setcaps (GstAudioDecoder * dec, GstCaps * caps);
+static GstFlowReturn gst_audio_decoder_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buf);
+static gboolean gst_audio_decoder_src_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
+static gboolean gst_audio_decoder_sink_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 static void gst_audio_decoder_reset (GstAudioDecoder * dec, gboolean full);
 
+static GstElementClass *parent_class = NULL;
 
-GST_BOILERPLATE (GstAudioDecoder, gst_audio_decoder, GstElement,
-    GST_TYPE_ELEMENT);
+static void gst_audio_decoder_class_init (GstAudioDecoderClass * klass);
+static void gst_audio_decoder_init (GstAudioDecoder * dec,
+    GstAudioDecoderClass * klass);
 
-static void
-gst_audio_decoder_base_init (gpointer g_class)
+GType
+gst_audio_decoder_get_type (void)
 {
+  static volatile gsize audio_decoder_type = 0;
+
+  if (g_once_init_enter (&audio_decoder_type)) {
+    GType _type;
+    static const GTypeInfo audio_decoder_info = {
+      sizeof (GstAudioDecoderClass),
+      NULL,
+      NULL,
+      (GClassInitFunc) gst_audio_decoder_class_init,
+      NULL,
+      NULL,
+      sizeof (GstAudioDecoder),
+      0,
+      (GInstanceInitFunc) gst_audio_decoder_init,
+    };
+
+    _type = g_type_register_static (GST_TYPE_ELEMENT,
+        "GstAudioDecoder", &audio_decoder_info, G_TYPE_FLAG_ABSTRACT);
+    g_once_init_leave (&audio_decoder_type, _type);
+  }
+  return audio_decoder_type;
 }
 
+
 static void
 gst_audio_decoder_class_init (GstAudioDecoderClass * klass)
 {
@@ -357,8 +386,6 @@ gst_audio_decoder_init (GstAudioDecoder * dec, GstAudioDecoderClass * klass)
   dec->sinkpad = gst_pad_new_from_template (pad_template, "sink");
   gst_pad_set_event_function (dec->sinkpad,
       GST_DEBUG_FUNCPTR (gst_audio_decoder_sink_event));
-  gst_pad_set_setcaps_function (dec->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_audio_decoder_sink_setcaps));
   gst_pad_set_chain_function (dec->sinkpad,
       GST_DEBUG_FUNCPTR (gst_audio_decoder_chain));
   gst_pad_set_query_function (dec->sinkpad,
@@ -372,14 +399,10 @@ gst_audio_decoder_init (GstAudioDecoder * dec, GstAudioDecoderClass * klass)
   g_return_if_fail (pad_template != NULL);
 
   dec->srcpad = gst_pad_new_from_template (pad_template, "src");
-  gst_pad_set_setcaps_function (dec->srcpad,
-      GST_DEBUG_FUNCPTR (gst_audio_decoder_src_setcaps));
   gst_pad_set_event_function (dec->srcpad,
       GST_DEBUG_FUNCPTR (gst_audio_decoder_src_event));
   gst_pad_set_query_function (dec->srcpad,
       GST_DEBUG_FUNCPTR (gst_audio_decoder_src_query));
-  gst_pad_set_query_type_function (dec->srcpad,
-      GST_DEBUG_FUNCPTR (gst_audio_decoder_get_query_types));
   gst_pad_use_fixed_caps (dec->srcpad);
   gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad);
   GST_DEBUG_OBJECT (dec, "srcpad created");
@@ -415,7 +438,7 @@ gst_audio_decoder_reset (GstAudioDecoder * dec, gboolean full)
     dec->priv->error_count = 0;
     gst_audio_decoder_clear_queues (dec);
 
-    gst_audio_info_clear (&dec->priv->ctx.info);
+    gst_audio_info_init (&dec->priv->ctx.info);
     memset (&dec->priv->ctx, 0, sizeof (dec->priv->ctx));
 
     if (dec->priv->taglist) {
@@ -466,17 +489,22 @@ gst_audio_decoder_finalize (GObject * object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-/* automagically perform sanity checking of src caps;
- * also extracts output data format */
-static gboolean
-gst_audio_decoder_src_setcaps (GstPad * pad, GstCaps * caps)
+/**
+ * gst_audio_decoder_set_outcaps:
+ * @dec: a #GstAudioDecoder
+ * @caps: #GstCaps
+ *
+ * Configure output @caps on the srcpad of @dec. Also perform
+ * sanity checking of @caps and extracts output data format
+ *
+ * Returns: %TRUE on success.
+ * */
+gboolean
+gst_audio_decoder_set_outcaps (GstAudioDecoder * dec, GstCaps * caps)
 {
-  GstAudioDecoder *dec;
   gboolean res = TRUE;
   guint old_rate;
 
-  dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
-
   GST_DEBUG_OBJECT (dec, "setting src caps %" GST_PTR_FORMAT, caps);
 
   GST_AUDIO_DECODER_STREAM_LOCK (dec);
@@ -500,7 +528,8 @@ gst_audio_decoder_src_setcaps (GstPad * pad, GstCaps * caps)
 done:
   GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
 
-  gst_object_unref (dec);
+  res = gst_pad_set_caps (dec->srcpad, caps);
+
   return res;
 
   /* ERRORS */
@@ -513,13 +542,11 @@ refuse_caps:
 }
 
 static gboolean
-gst_audio_decoder_sink_setcaps (GstPad * pad, GstCaps * caps)
+gst_audio_decoder_sink_setcaps (GstAudioDecoder * dec, GstCaps * caps)
 {
-  GstAudioDecoder *dec;
   GstAudioDecoderClass *klass;
   gboolean res = TRUE;
 
-  dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
   klass = GST_AUDIO_DECODER_GET_CLASS (dec);
 
   GST_DEBUG_OBJECT (dec, "caps: %" GST_PTR_FORMAT, caps);
@@ -527,18 +554,19 @@ gst_audio_decoder_sink_setcaps (GstPad * pad, GstCaps * caps)
   GST_AUDIO_DECODER_STREAM_LOCK (dec);
   /* NOTE pbutils only needed here */
   /* TODO maybe (only) upstream demuxer/parser etc should handle this ? */
+#if 0
   if (dec->priv->taglist)
     gst_tag_list_free (dec->priv->taglist);
   dec->priv->taglist = gst_tag_list_new ();
   gst_pb_utils_add_codec_description_to_tag_list (dec->priv->taglist,
       GST_TAG_AUDIO_CODEC, caps);
+#endif
 
   if (klass->set_format)
     res = klass->set_format (dec, caps);
 
   GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
 
-  g_object_unref (dec);
   return res;
 }
 
@@ -580,8 +608,9 @@ gst_audio_decoder_push_forward (GstAudioDecoder * dec, GstBuffer * buf)
     return GST_FLOW_OK;
   }
 
-  GST_LOG_OBJECT (dec, "clipping buffer of size %d with ts %" GST_TIME_FORMAT
-      ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
+  GST_LOG_OBJECT (dec,
+      "clipping buffer of size %" G_GSIZE_FORMAT " with ts %" GST_TIME_FORMAT
+      ", duration %" GST_TIME_FORMAT, gst_buffer_get_size (buf),
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
 
@@ -594,8 +623,6 @@ gst_audio_decoder_push_forward (GstAudioDecoder * dec, GstBuffer * buf)
   }
 
   /* decorate */
-  gst_buffer_set_caps (buf, GST_PAD_CAPS (dec->srcpad));
-
   if (G_UNLIKELY (priv->discont)) {
     GST_LOG_OBJECT (dec, "marking discont");
     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT);
@@ -606,7 +633,7 @@ gst_audio_decoder_push_forward (GstAudioDecoder * dec, GstBuffer * buf)
   if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) {
     /* duration should always be valid for raw audio */
     g_assert (GST_BUFFER_DURATION_IS_VALID (buf));
-    dec->segment.last_stop =
+    dec->segment.position =
         GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf);
   }
 
@@ -622,8 +649,9 @@ gst_audio_decoder_push_forward (GstAudioDecoder * dec, GstBuffer * buf)
     }
   }
 
-  GST_LOG_OBJECT (dec, "pushing buffer of size %d with ts %" GST_TIME_FORMAT
-      ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
+  GST_LOG_OBJECT (dec,
+      "pushing buffer of size %" G_GSIZE_FORMAT " with ts %" GST_TIME_FORMAT
+      ", duration %" GST_TIME_FORMAT, gst_buffer_get_size (buf),
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
 
@@ -648,8 +676,9 @@ gst_audio_decoder_output (GstAudioDecoder * dec, GstBuffer * buf)
     gst_audio_decoder_setup (dec);
 
   if (G_LIKELY (buf)) {
-    GST_LOG_OBJECT (dec, "output buffer of size %d with ts %" GST_TIME_FORMAT
-        ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buf),
+    GST_LOG_OBJECT (dec,
+        "output buffer of size %" G_GSIZE_FORMAT " with ts %" GST_TIME_FORMAT
+        ", duration %" GST_TIME_FORMAT, gst_buffer_get_size (buf),
         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
         GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
   }
@@ -684,7 +713,7 @@ again:
       }
       gst_adapter_push (priv->adapter_out, buf);
       priv->out_dur += GST_BUFFER_DURATION (buf);
-      av += GST_BUFFER_SIZE (buf);
+      av += gst_buffer_get_size (buf);
       buf = NULL;
     }
     if (priv->out_dur > dec->priv->latency)
@@ -748,27 +777,30 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf,
   GstAudioDecoderContext *ctx;
   gint samples = 0;
   GstClockTime ts, next_ts;
+  gsize size;
   GstFlowReturn ret = GST_FLOW_OK;
 
   /* subclass should know what it is producing by now */
-  g_return_val_if_fail (buf == NULL || GST_PAD_CAPS (dec->srcpad) != NULL,
+  g_return_val_if_fail (buf == NULL || gst_pad_has_current_caps (dec->srcpad),
       GST_FLOW_ERROR);
   /* subclass should not hand us no data */
-  g_return_val_if_fail (buf == NULL || GST_BUFFER_SIZE (buf) > 0,
+  g_return_val_if_fail (buf == NULL || gst_buffer_get_size (buf) > 0,
       GST_FLOW_ERROR);
   /* no dummy calls please */
   g_return_val_if_fail (frames != 0, GST_FLOW_ERROR);
 
   priv = dec->priv;
   ctx = &dec->priv->ctx;
+  size = buf ? gst_buffer_get_size (buf) : 0;
 
   /* must know the output format by now */
   g_return_val_if_fail (buf == NULL || GST_AUDIO_INFO_IS_VALID (&ctx->info),
       GST_FLOW_ERROR);
 
-  GST_LOG_OBJECT (dec, "accepting %d bytes == %d samples for %d frames",
-      buf ? GST_BUFFER_SIZE (buf) : -1,
-      buf ? GST_BUFFER_SIZE (buf) / ctx->info.bpf : -1, frames);
+  GST_LOG_OBJECT (dec,
+      "accepting %" G_GSIZE_FORMAT " bytes == %" G_GSIZE_FORMAT
+      " samples for %d frames", buf ? size : -1,
+      buf ? size / ctx->info.bpf : -1, frames);
 
   GST_AUDIO_DECODER_STREAM_LOCK (dec);
 
@@ -786,10 +818,10 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf,
 
   /* output shoud be whole number of sample frames */
   if (G_LIKELY (buf && ctx->info.bpf)) {
-    if (GST_BUFFER_SIZE (buf) % ctx->info.bpf)
+    if (size % ctx->info.bpf)
       goto wrong_buffer;
     /* per channel least */
-    samples = GST_BUFFER_SIZE (buf) / ctx->info.bpf;
+    samples = size / ctx->info.bpf;
   }
 
   /* frame and ts book-keeping */
@@ -865,12 +897,12 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf,
     if (gst_tag_list_is_empty (priv->taglist)) {
       gst_tag_list_free (priv->taglist);
     } else {
-      gst_element_found_tags (GST_ELEMENT (dec), priv->taglist);
+      gst_pad_push_event (dec->srcpad, gst_event_new_tag (priv->taglist));
     }
     priv->taglist = NULL;
   }
 
-  buf = gst_buffer_make_metadata_writable (buf);
+  buf = gst_buffer_make_writable (buf);
   if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (priv->base_ts))) {
     GST_BUFFER_TIMESTAMP (buf) =
         priv->base_ts +
@@ -901,7 +933,7 @@ exit:
 wrong_buffer:
   {
     GST_ELEMENT_ERROR (dec, STREAM, ENCODE, (NULL),
-        ("buffer size %d not a multiple of %d", GST_BUFFER_SIZE (buf),
+        ("buffer size %" G_GSIZE_FORMAT " not a multiple of %d", size,
             ctx->info.bpf));
     gst_buffer_unref (buf);
     ret = GST_FLOW_ERROR;
@@ -924,13 +956,14 @@ gst_audio_decoder_handle_frame (GstAudioDecoder * dec,
     GstAudioDecoderClass * klass, GstBuffer * buffer)
 {
   if (G_LIKELY (buffer)) {
+    gsize size = gst_buffer_get_size (buffer);
     /* keep around for admin */
-    GST_LOG_OBJECT (dec, "tracking frame size %d, ts %" GST_TIME_FORMAT,
-        GST_BUFFER_SIZE (buffer),
+    GST_LOG_OBJECT (dec,
+        "tracking frame size %" G_GSIZE_FORMAT ", ts %" GST_TIME_FORMAT, size,
         GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)));
     g_queue_push_tail (&dec->priv->frames, buffer);
     dec->priv->ctx.delay = dec->priv->frames.length;
-    dec->priv->bytes_in += GST_BUFFER_SIZE (buffer);
+    dec->priv->bytes_in += size;
   } else {
     GST_LOG_OBJECT (dec, "providing subclass with NULL frame");
   }
@@ -992,7 +1025,7 @@ gst_audio_decoder_push_buffers (GstAudioDecoder * dec, gboolean force)
             goto parse_failed;
         }
 
-        if (ret == GST_FLOW_UNEXPECTED) {
+        if (ret == GST_FLOW_EOS) {
           GST_LOG_OBJECT (dec, "no frame yet");
           ret = GST_FLOW_OK;
           break;
@@ -1015,7 +1048,7 @@ gst_audio_decoder_push_buffers (GstAudioDecoder * dec, gboolean force)
         priv->prev_ts = ts;
       }
       buffer = gst_adapter_take_buffer (priv->adapter, len);
-      buffer = gst_buffer_make_metadata_writable (buffer);
+      buffer = gst_buffer_make_writable (buffer);
       GST_BUFFER_TIMESTAMP (buffer) = ts;
       flush += len;
     } else {
@@ -1113,7 +1146,7 @@ gst_audio_decoder_chain_forward (GstAudioDecoder * dec, GstBuffer * buffer)
   GstFlowReturn ret = GST_FLOW_OK;
 
   /* discard silly case, though maybe ts may be of value ?? */
-  if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) == 0)) {
+  if (G_UNLIKELY (gst_buffer_get_size (buffer) == 0)) {
     GST_DEBUG_OBJECT (dec, "discarding empty buffer");
     gst_buffer_unref (buffer);
     goto exit;
@@ -1278,12 +1311,12 @@ gst_audio_decoder_flush_decode (GstAudioDecoder * dec)
     }
 
     if (G_LIKELY (res == GST_FLOW_OK)) {
-      GST_DEBUG_OBJECT (dec, "pushing buffer %p of size %u, "
+      GST_DEBUG_OBJECT (dec, "pushing buffer %p of size %" G_GSIZE_FORMAT ", "
           "time %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT, buf,
-          GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
+          gst_buffer_get_size (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
           GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
       /* should be already, but let's be sure */
-      buf = gst_buffer_make_metadata_writable (buf);
+      buf = gst_buffer_make_writable (buf);
       /* avoid stray DISCONT from forward processing,
        * which have no meaning in reverse pushing */
       GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT);
@@ -1321,9 +1354,9 @@ gst_audio_decoder_chain_reverse (GstAudioDecoder * dec, GstBuffer * buf)
   }
 
   if (G_LIKELY (buf)) {
-    GST_DEBUG_OBJECT (dec, "gathering buffer %p of size %u, "
+    GST_DEBUG_OBJECT (dec, "gathering buffer %p of size %" G_GSIZE_FORMAT ", "
         "time %" GST_TIME_FORMAT ", dur %" GST_TIME_FORMAT, buf,
-        GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
+        gst_buffer_get_size (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
         GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
 
     /* add buffer to gather queue */
@@ -1334,16 +1367,16 @@ gst_audio_decoder_chain_reverse (GstAudioDecoder * dec, GstBuffer * buf)
 }
 
 static GstFlowReturn
-gst_audio_decoder_chain (GstPad * pad, GstBuffer * buffer)
+gst_audio_decoder_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstAudioDecoder *dec;
   GstFlowReturn ret;
 
-  dec = GST_AUDIO_DECODER (GST_PAD_PARENT (pad));
+  dec = GST_AUDIO_DECODER (parent);
 
   GST_LOG_OBJECT (dec,
-      "received buffer of size %d with ts %" GST_TIME_FORMAT
-      ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer),
+      "received buffer of size %" G_GSIZE_FORMAT " with ts %" GST_TIME_FORMAT
+      ", duration %" GST_TIME_FORMAT, gst_buffer_get_size (buffer),
       GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
       GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
 
@@ -1395,47 +1428,37 @@ gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event)
   gboolean handled = FALSE;
 
   switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
     {
-      GstFormat format;
-      gdouble rate, arate;
-      gint64 start, stop, time;
-      gboolean update;
+      GstSegment seg;
 
       GST_AUDIO_DECODER_STREAM_LOCK (dec);
-      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
-          &start, &stop, &time);
+      gst_event_copy_segment (event, &seg);
 
-      if (format == GST_FORMAT_TIME) {
-        GST_DEBUG_OBJECT (dec, "received TIME NEW_SEGMENT %" GST_TIME_FORMAT
-            " -- %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT
-            ", rate %g, applied_rate %g",
-            GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time),
-            rate, arate);
+      if (seg.format == GST_FORMAT_TIME) {
+        GST_DEBUG_OBJECT (dec, "received TIME SEGMENT %" GST_SEGMENT_FORMAT,
+            &seg);
       } else {
-        GstFormat dformat = GST_FORMAT_TIME;
-
-        GST_DEBUG_OBJECT (dec, "received NEW_SEGMENT %" G_GINT64_FORMAT
-            " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT
-            ", rate %g, applied_rate %g", start, stop, time, rate, arate);
+        gint64 nstart;
+        GST_DEBUG_OBJECT (dec, "received SEGMENT %" GST_SEGMENT_FORMAT, &seg);
         /* handle newsegment resulting from legacy simple seeking */
         /* note that we need to convert this whether or not enough data
          * to handle initial newsegment */
         if (dec->priv->ctx.do_byte_time &&
-            gst_pad_query_convert (dec->sinkpad, GST_FORMAT_BYTES, start,
-                &dformat, &start)) {
+            gst_pad_query_convert (dec->sinkpad, GST_FORMAT_BYTES, seg.start,
+                GST_FORMAT_TIME, &nstart)) {
           /* best attempt convert */
           /* as these are only estimates, stop is kept open-ended to avoid
            * premature cutting */
           GST_DEBUG_OBJECT (dec, "converted to TIME start %" GST_TIME_FORMAT,
-              GST_TIME_ARGS (start));
-          format = GST_FORMAT_TIME;
-          time = start;
-          stop = GST_CLOCK_TIME_NONE;
+              GST_TIME_ARGS (nstart));
+          seg.format = GST_FORMAT_TIME;
+          seg.start = nstart;
+          seg.time = nstart;
+          seg.stop = GST_CLOCK_TIME_NONE;
           /* replace event */
           gst_event_unref (event);
-          event = gst_event_new_new_segment_full (update, rate, arate,
-              GST_FORMAT_TIME, start, stop, time);
+          event = gst_event_new_segment (&seg);
         } else {
           GST_DEBUG_OBJECT (dec, "unsupported format; ignoring");
           GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
@@ -1446,41 +1469,42 @@ gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event)
       /* finish current segment */
       gst_audio_decoder_drain (dec);
 
+#if 0
       if (update) {
         /* time progressed without data, see if we can fill the gap with
          * some concealment data */
         GST_DEBUG_OBJECT (dec,
-            "segment update: plc %d, do_plc %d, last_stop %" GST_TIME_FORMAT,
+            "segment update: plc %d, do_plc %d, position %" GST_TIME_FORMAT,
             dec->priv->plc, dec->priv->ctx.do_plc,
-            GST_TIME_ARGS (dec->segment.last_stop));
+            GST_TIME_ARGS (dec->segment.position));
         if (dec->priv->plc && dec->priv->ctx.do_plc &&
-            dec->segment.rate > 0.0 && dec->segment.last_stop < start) {
+            dec->segment.rate > 0.0 && dec->segment.position < start) {
           GstAudioDecoderClass *klass;
           GstBuffer *buf;
 
           klass = GST_AUDIO_DECODER_GET_CLASS (dec);
           /* hand subclass empty frame with duration that needs covering */
           buf = gst_buffer_new ();
-          GST_BUFFER_DURATION (buf) = start - dec->segment.last_stop;
+          GST_BUFFER_DURATION (buf) = start - dec->segment.position;
           /* best effort, not much error handling */
           gst_audio_decoder_handle_frame (dec, klass, buf);
         }
-      } else {
+      } else
+#endif
+      {
         /* prepare for next one */
         gst_audio_decoder_flush (dec, FALSE);
         /* and that's where we time from,
          * in case upstream does not come up with anything better
          * (e.g. upstream BYTE) */
-        if (format != GST_FORMAT_TIME) {
-          dec->priv->base_ts = start;
+        if (seg.format != GST_FORMAT_TIME) {
+          dec->priv->base_ts = seg.start;
           dec->priv->samples = 0;
         }
       }
 
       /* and follow along with segment */
-      gst_segment_set_newsegment_full (&dec->segment, update, rate, arate,
-          format, start, stop, time);
-
+      dec->segment = seg;
       dec->priv->pending_events =
           g_list_append (dec->priv->pending_events, event);
       handled = TRUE;
@@ -1508,6 +1532,16 @@ gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event)
       GST_AUDIO_DECODER_STREAM_UNLOCK (dec);
       break;
 
+    case GST_EVENT_CAPS:
+    {
+      GstCaps *caps;
+
+      gst_event_parse_caps (event, &caps);
+      gst_audio_decoder_sink_setcaps (dec, caps);
+      gst_event_unref (event);
+      handled = TRUE;
+      break;
+    }
     default:
       break;
   }
@@ -1516,14 +1550,15 @@ gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event)
 }
 
 static gboolean
-gst_audio_decoder_sink_event (GstPad * pad, GstEvent * event)
+gst_audio_decoder_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event)
 {
   GstAudioDecoder *dec;
   GstAudioDecoderClass *klass;
   gboolean handled = FALSE;
   gboolean ret = TRUE;
 
-  dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
+  dec = GST_AUDIO_DECODER (parent);
   klass = GST_AUDIO_DECODER_GET_CLASS (dec);
 
   GST_DEBUG_OBJECT (dec, "received event %d, %s", GST_EVENT_TYPE (event),
@@ -1547,7 +1582,7 @@ gst_audio_decoder_sink_event (GstPad * pad, GstEvent * event)
     if (!GST_EVENT_IS_SERIALIZED (event)
         || GST_EVENT_TYPE (event) == GST_EVENT_EOS
         || GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) {
-      ret = gst_pad_event_default (pad, event);
+      ret = gst_pad_event_default (pad, parent, event);
     } else {
       GST_AUDIO_DECODER_STREAM_LOCK (dec);
       dec->priv->pending_events =
@@ -1559,7 +1594,6 @@ gst_audio_decoder_sink_event (GstPad * pad, GstEvent * event)
 
   GST_DEBUG_OBJECT (dec, "event handled");
 
-  gst_object_unref (dec);
   return ret;
 }
 
@@ -1600,13 +1634,12 @@ gst_audio_decoder_do_seek (GstAudioDecoder * dec, GstEvent * event)
   }
 
   memcpy (&seek_segment, &dec->segment, sizeof (seek_segment));
-  gst_segment_set_seek (&seek_segment, rate, format, flags, start_type,
+  gst_segment_do_seek (&seek_segment, rate, format, flags, start_type,
       start_time, end_type, end_time, NULL);
-  start_time = seek_segment.last_stop;
+  start_time = seek_segment.position;
 
-  format = GST_FORMAT_BYTES;
   if (!gst_pad_query_convert (dec->sinkpad, GST_FORMAT_TIME, start_time,
-          &format, &start)) {
+          GST_FORMAT_BYTES, &start)) {
     GST_DEBUG_OBJECT (dec, "conversion failed");
     return FALSE;
   }
@@ -1623,16 +1656,12 @@ gst_audio_decoder_do_seek (GstAudioDecoder * dec, GstEvent * event)
 }
 
 static gboolean
-gst_audio_decoder_src_event (GstPad * pad, GstEvent * event)
+gst_audio_decoder_src_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstAudioDecoder *dec;
   gboolean res = FALSE;
 
-  dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
-  if (G_UNLIKELY (dec == NULL)) {
-    gst_event_unref (event);
-    return FALSE;
-  }
+  dec = GST_AUDIO_DECODER (parent);
 
   GST_DEBUG_OBJECT (dec, "received event %d, %s", GST_EVENT_TYPE (event),
       GST_EVENT_TYPE_NAME (event));
@@ -1640,7 +1669,7 @@ gst_audio_decoder_src_event (GstPad * pad, GstEvent * event)
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_SEEK:
     {
-      GstFormat format, tformat;
+      GstFormat format;
       gdouble rate;
       GstSeekFlags flags;
       GstSeekType cur_type, stop_type;
@@ -1665,10 +1694,12 @@ gst_audio_decoder_src_event (GstPad * pad, GstEvent * event)
 
       /* ... though a non-time seek can be aided as well */
       /* First bring the requested format to time */
-      tformat = GST_FORMAT_TIME;
-      if (!(res = gst_pad_query_convert (pad, format, cur, &tformat, &tcur)))
+      if (!(res =
+              gst_pad_query_convert (pad, format, cur, GST_FORMAT_TIME, &tcur)))
         goto convert_error;
-      if (!(res = gst_pad_query_convert (pad, format, stop, &tformat, &tstop)))
+      if (!(res =
+              gst_pad_query_convert (pad, format, stop, GST_FORMAT_TIME,
+                  &tstop)))
         goto convert_error;
 
       /* then seek with time on the peer */
@@ -1684,8 +1715,6 @@ gst_audio_decoder_src_event (GstPad * pad, GstEvent * event)
       break;
   }
 done:
-  gst_object_unref (dec);
-
   return res;
 
   /* ERRORS */
@@ -1768,12 +1797,13 @@ exit:
 }
 
 static gboolean
-gst_audio_decoder_sink_query (GstPad * pad, GstQuery * query)
+gst_audio_decoder_sink_query (GstPad * pad, GstObject * parent,
+    GstQuery * query)
 {
-  gboolean res = TRUE;
+  gboolean res = FALSE;
   GstAudioDecoder *dec;
 
-  dec = GST_AUDIO_DECODER (gst_pad_get_parent (pad));
+  dec = GST_AUDIO_DECODER (parent);
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_FORMATS:
@@ -1796,45 +1826,25 @@ gst_audio_decoder_sink_query (GstPad * pad, GstQuery * query)
       break;
     }
     default:
-      res = gst_pad_query_default (pad, query);
+      res = gst_pad_query_default (pad, parent, query);
       break;
   }
 
 error:
-  gst_object_unref (dec);
   return res;
 }
 
-static const GstQueryType *
-gst_audio_decoder_get_query_types (GstPad * pad)
-{
-  static const GstQueryType gst_audio_decoder_src_query_types[] = {
-    GST_QUERY_POSITION,
-    GST_QUERY_DURATION,
-    GST_QUERY_CONVERT,
-    GST_QUERY_LATENCY,
-    0
-  };
-
-  return gst_audio_decoder_src_query_types;
-}
-
 /* FIXME ? are any of these queries (other than latency) a decoder's business ??
  * also, the conversion stuff might seem to make sense, but seems to not mind
  * segment stuff etc at all
  * Supposedly that's backward compatibility ... */
 static gboolean
-gst_audio_decoder_src_query (GstPad * pad, GstQuery * query)
+gst_audio_decoder_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
   GstAudioDecoder *dec;
-  GstPad *peerpad;
   gboolean res = FALSE;
 
-  dec = GST_AUDIO_DECODER (GST_PAD_PARENT (pad));
-  if (G_UNLIKELY (dec == NULL))
-    return FALSE;
-
-  peerpad = gst_pad_get_peer (GST_PAD (dec->sinkpad));
+  dec = GST_AUDIO_DECODER (parent);
 
   GST_LOG_OBJECT (dec, "handling query: %" GST_PTR_FORMAT, query);
 
@@ -1844,7 +1854,7 @@ gst_audio_decoder_src_query (GstPad * pad, GstQuery * query)
       GstFormat format;
 
       /* upstream in any case */
-      if ((res = gst_pad_query_default (pad, query)))
+      if ((res = gst_pad_query_default (pad, parent, query)))
         break;
 
       gst_query_parse_duration (query, &format, NULL);
@@ -1852,12 +1862,11 @@ gst_audio_decoder_src_query (GstPad * pad, GstQuery * query)
       if (format == GST_FORMAT_TIME && gst_audio_decoder_do_byte (dec)) {
         gint64 value;
 
-        format = GST_FORMAT_BYTES;
-        if (gst_pad_query_peer_duration (dec->sinkpad, &format, &value)) {
+        if (gst_pad_peer_query_duration (dec->sinkpad, GST_FORMAT_BYTES,
+                &value)) {
           GST_LOG_OBJECT (dec, "upstream size %" G_GINT64_FORMAT, value);
-          format = GST_FORMAT_TIME;
           if (gst_pad_query_convert (dec->sinkpad, GST_FORMAT_BYTES, value,
-                  &format, &value)) {
+                  GST_FORMAT_TIME, &value)) {
             gst_query_set_duration (query, GST_FORMAT_TIME, value);
             res = TRUE;
           }
@@ -1876,7 +1885,7 @@ gst_audio_decoder_src_query (GstPad * pad, GstQuery * query)
       }
 
       /* we start from the last seen time */
-      time = dec->segment.last_stop;
+      time = dec->segment.position;
       /* correct for the segment values */
       time = gst_segment_to_stream_time (&dec->segment, GST_FORMAT_TIME, time);
 
@@ -1886,7 +1895,7 @@ gst_audio_decoder_src_query (GstPad * pad, GstQuery * query)
       /* and convert to the final format */
       gst_query_parse_position (query, &format, NULL);
       if (!(res = gst_pad_query_convert (pad, GST_FORMAT_TIME, time,
-                  &format, &value)))
+                  format, &value)))
         break;
 
       gst_query_set_position (query, format, value);
@@ -1939,11 +1948,10 @@ gst_audio_decoder_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 (peerpad);
   return res;
 }
 
@@ -2063,7 +2071,7 @@ gst_audio_decoder_change_state (GstElement * element, GstStateChange transition)
       break;
   }
 
-  ret = parent_class->change_state (element, transition);
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
 
   switch (transition) {
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED: