Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / gst / isomp4 / qtdemux.c
index 7830017..784648e 100644 (file)
@@ -33,7 +33,7 @@
  * <refsect2>
  * <title>Example launch line</title>
  * |[
- * gst-launch filesrc location=test.mov ! qtdemux name=demux  demux.audio_00 ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_00 ! queue ! decodebin ! ffmpegcolorspace ! videoscale ! autovideosink
+ * gst-launch filesrc location=test.mov ! qtdemux name=demux  demux.audio_0 ! decodebin ! audioconvert ! audioresample ! autoaudiosink   demux.video_0 ! queue ! decodebin ! ffmpegcolorspace ! videoscale ! autovideosink
  * ]| Play (parse and decode) a .mov file and try to output it to
  * an automatically detected soundcard and videosink. If the MOV file contains
  * compressed audio or video data, this will only work if you have the
@@ -51,6 +51,7 @@
 
 #include <glib/gprintf.h>
 #include <gst/tag/tag.h>
+#include <gst/audio/audio.h>
 
 #include "qtatomparser.h"
 #include "qtdemux_types.h"
@@ -366,24 +367,25 @@ static GstStaticPadTemplate gst_qtdemux_sink_template =
     );
 
 static GstStaticPadTemplate gst_qtdemux_videosrc_template =
-GST_STATIC_PAD_TEMPLATE ("video_%02d",
+GST_STATIC_PAD_TEMPLATE ("video_%u",
     GST_PAD_SRC,
     GST_PAD_SOMETIMES,
     GST_STATIC_CAPS_ANY);
 
 static GstStaticPadTemplate gst_qtdemux_audiosrc_template =
-GST_STATIC_PAD_TEMPLATE ("audio_%02d",
+GST_STATIC_PAD_TEMPLATE ("audio_%u",
     GST_PAD_SRC,
     GST_PAD_SOMETIMES,
     GST_STATIC_CAPS_ANY);
 
 static GstStaticPadTemplate gst_qtdemux_subsrc_template =
-GST_STATIC_PAD_TEMPLATE ("subtitle_%02d",
+GST_STATIC_PAD_TEMPLATE ("subtitle_%u",
     GST_PAD_SRC,
     GST_PAD_SOMETIMES,
     GST_STATIC_CAPS_ANY);
 
-GST_BOILERPLATE (GstQTDemux, gst_qtdemux, GstQTDemux, GST_TYPE_ELEMENT);
+#define gst_qtdemux_parent_class parent_class
+G_DEFINE_TYPE (GstQTDemux, gst_qtdemux, GST_TYPE_ELEMENT);
 
 static void gst_qtdemux_dispose (GObject * object);
 
@@ -428,27 +430,6 @@ static gboolean qtdemux_parse_samples (GstQTDemux * qtdemux,
 static GstFlowReturn qtdemux_expose_streams (GstQTDemux * qtdemux);
 
 static void
-gst_qtdemux_base_init (gpointer klass)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_qtdemux_sink_template));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_qtdemux_videosrc_template));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_qtdemux_audiosrc_template));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&gst_qtdemux_subsrc_template));
-  gst_element_class_set_details_simple (element_class, "QuickTime demuxer",
-      "Codec/Demuxer",
-      "Demultiplex a QuickTime file into audio and video streams",
-      "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
-
-  GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
-}
-
-static void
 gst_qtdemux_class_init (GstQTDemuxClass * klass)
 {
   GObjectClass *gobject_class;
@@ -467,10 +448,26 @@ gst_qtdemux_class_init (GstQTDemuxClass * klass)
   gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_qtdemux_get_index);
 
   gst_tag_register_musicbrainz_tags ();
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&gst_qtdemux_sink_template));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&gst_qtdemux_videosrc_template));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&gst_qtdemux_audiosrc_template));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&gst_qtdemux_subsrc_template));
+  gst_element_class_set_details_simple (gstelement_class, "QuickTime demuxer",
+      "Codec/Demuxer",
+      "Demultiplex a QuickTime file into audio and video streams",
+      "David Schleef <ds@schleef.org>, Wim Taymans <wim@fluendo.com>");
+
+  GST_DEBUG_CATEGORY_INIT (qtdemux_debug, "qtdemux", 0, "qtdemux plugin");
+
 }
 
 static void
-gst_qtdemux_init (GstQTDemux * qtdemux, GstQTDemuxClass * klass)
+gst_qtdemux_init (GstQTDemux * qtdemux)
 {
   qtdemux->sinkpad =
       gst_pad_new_from_static_template (&gst_qtdemux_sink_template, "sink");
@@ -524,11 +521,43 @@ gst_qtdemux_post_no_playable_stream_error (GstQTDemux * qtdemux)
   }
 }
 
+static void
+_gst_buffer_copy_into_mem (GstBuffer * dest, const guint8 * src,
+    gsize offset, gsize size)
+{
+  guint8 *bdata;
+  gsize bsize;
+
+  g_return_if_fail (gst_buffer_is_writable (dest));
+
+  bsize = gst_buffer_get_size (dest);
+  g_return_if_fail (bsize >= offset + size);
+
+  bdata = gst_buffer_map (dest, &bsize, NULL, GST_MAP_WRITE);
+  memcpy (bdata + offset, src, size);
+  gst_buffer_unmap (dest, bdata, bsize);
+}
+
+static GstBuffer *
+_gst_buffer_new_wrapped (gpointer mem, gsize size, GFreeFunc free_func)
+{
+  GstBuffer *buf;
+
+  buf = gst_buffer_new ();
+  gst_buffer_take_memory (buf, -1,
+      gst_memory_new_wrapped (free_func ? 0 : GST_MEMORY_FLAG_READONLY,
+          mem, free_func, size, 0, size));
+
+  return buf;
+}
+
 static GstFlowReturn
 gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
     GstBuffer ** buf)
 {
   GstFlowReturn flow;
+  guint8 *bdata;
+  gsize bsize;
 
   if (G_UNLIKELY (size == 0)) {
     GstFlowReturn ret;
@@ -538,9 +567,11 @@ gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
     if (ret != GST_FLOW_OK)
       return ret;
 
-    size = QT_UINT32 (GST_BUFFER_DATA (tmp));
+    bdata = gst_buffer_map (tmp, &bsize, NULL, GST_MAP_READ);
+    size = QT_UINT32 (bdata);
     GST_DEBUG_OBJECT (qtdemux, "size 0x%08" G_GINT64_MODIFIER "x", size);
 
+    gst_buffer_unmap (tmp, bdata, bsize);
     gst_buffer_unref (tmp);
   }
 
@@ -565,10 +596,11 @@ gst_qtdemux_pull_atom (GstQTDemux * qtdemux, guint64 offset, guint64 size,
   if (G_UNLIKELY (flow != GST_FLOW_OK))
     return flow;
 
+  bsize = gst_buffer_get_size (*buf);
   /* Catch short reads - we don't want any partial atoms */
-  if (G_UNLIKELY (GST_BUFFER_SIZE (*buf) < size)) {
+  if (G_UNLIKELY (bsize < size)) {
     GST_WARNING_OBJECT (qtdemux, "short read: %u < %" G_GUINT64_FORMAT,
-        GST_BUFFER_SIZE (*buf), size);
+        bsize, size);
     gst_buffer_unref (*buf);
     *buf = NULL;
     return GST_FLOW_UNEXPECTED;
@@ -646,21 +678,6 @@ done:
 }
 #endif
 
-static const GstQueryType *
-gst_qtdemux_get_src_query_types (GstPad * pad)
-{
-  static const GstQueryType src_types[] = {
-    GST_QUERY_POSITION,
-    GST_QUERY_DURATION,
-    GST_QUERY_CONVERT,
-    GST_QUERY_FORMATS,
-    GST_QUERY_SEEKING,
-    0
-  };
-
-  return src_types;
-}
-
 static gboolean
 gst_qtdemux_get_duration (GstQTDemux * qtdemux, gint64 * duration)
 {
@@ -687,9 +704,9 @@ gst_qtdemux_handle_src_query (GstPad * pad, GstQuery * query)
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_POSITION:
-      if (GST_CLOCK_TIME_IS_VALID (qtdemux->segment.last_stop)) {
+      if (GST_CLOCK_TIME_IS_VALID (qtdemux->segment.position)) {
         gst_query_set_position (query, GST_FORMAT_TIME,
-            qtdemux->segment.last_stop);
+            qtdemux->segment.position);
         res = TRUE;
       }
       break;
@@ -1106,8 +1123,9 @@ gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
 
     /* get the index of the sample with media time */
     index = gst_qtdemux_find_index_linear (qtdemux, str, media_start);
-    GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u",
-        GST_TIME_ARGS (media_start), index);
+    GST_DEBUG_OBJECT (qtdemux, "sample for %" GST_TIME_FORMAT " at %u"
+        " at offset %" G_GUINT64_FORMAT,
+        GST_TIME_ARGS (media_start), index, str->samples[index].offset);
 
     /* find previous keyframe */
     kindex = gst_qtdemux_find_keyframe (qtdemux, str, index);
@@ -1121,8 +1139,9 @@ gst_qtdemux_adjust_seek (GstQTDemux * qtdemux, gint64 desired_time,
       media_time =
           gst_util_uint64_scale (str->samples[kindex].timestamp, GST_SECOND,
           str->timescale);
-      GST_DEBUG_OBJECT (qtdemux, "keyframe at %u with time %" GST_TIME_FORMAT,
-          kindex, GST_TIME_ARGS (media_time));
+      GST_DEBUG_OBJECT (qtdemux, "keyframe at %u with time %" GST_TIME_FORMAT
+          " at offset %" G_GUINT64_FORMAT,
+          kindex, GST_TIME_ARGS (media_time), str->samples[kindex].offset);
 
       /* keyframes in the segment get a chance to change the
        * desired_offset. keyframes out of the segment are
@@ -1153,7 +1172,6 @@ gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
     GstSeekType cur_type, gint64 * cur, GstSeekType stop_type, gint64 * stop)
 {
   gboolean res;
-  GstFormat fmt;
 
   g_return_val_if_fail (format != NULL, FALSE);
   g_return_val_if_fail (cur != NULL, FALSE);
@@ -1162,12 +1180,11 @@ gst_qtdemux_convert_seek (GstPad * pad, GstFormat * format,
   if (*format == GST_FORMAT_TIME)
     return TRUE;
 
-  fmt = GST_FORMAT_TIME;
   res = TRUE;
   if (cur_type != GST_SEEK_TYPE_NONE)
-    res = gst_pad_query_convert (pad, *format, *cur, &fmt, cur);
+    res = gst_pad_query_convert (pad, *format, *cur, GST_FORMAT_TIME, cur);
   if (res && stop_type != GST_SEEK_TYPE_NONE)
-    res = gst_pad_query_convert (pad, *format, *stop, &fmt, stop);
+    res = gst_pad_query_convert (pad, *format, *stop, GST_FORMAT_TIME, stop);
 
   if (res)
     *format = GST_FORMAT_TIME;
@@ -1276,12 +1293,15 @@ gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment)
   gint64 desired_offset;
   gint n;
 
-  desired_offset = segment->last_stop;
+  desired_offset = segment->position;
 
   GST_DEBUG_OBJECT (qtdemux, "seeking to %" GST_TIME_FORMAT,
       GST_TIME_ARGS (desired_offset));
 
-  if (segment->flags & GST_SEEK_FLAG_KEY_UNIT) {
+  /* may not have enough fragmented info to do this adjustment,
+   * and we can't scan (and probably should not) at this time with
+   * possibly flushing upstream */
+  if ((segment->flags & GST_SEEK_FLAG_KEY_UNIT) && !qtdemux->fragmented) {
     gint64 min_offset;
 
     gst_qtdemux_adjust_seek (qtdemux, desired_offset, &min_offset, NULL);
@@ -1299,8 +1319,11 @@ gst_qtdemux_perform_seek (GstQTDemux * qtdemux, GstSegment * segment)
     stream->segment_index = -1;
     stream->last_ret = GST_FLOW_OK;
     stream->sent_eos = FALSE;
+
+    if (segment->flags & GST_SEEK_FLAG_FLUSH)
+      gst_segment_init (&stream->segment, GST_FORMAT_TIME);
   }
-  segment->last_stop = desired_offset;
+  segment->position = desired_offset;
   segment->time = desired_offset;
 
   /* we stop at the end */
@@ -1365,7 +1388,7 @@ gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
   if (event) {
     /* configure the segment with the seek variables */
     GST_DEBUG_OBJECT (qtdemux, "configuring seek");
-    gst_segment_set_seek (&seeksegment, rate, format, flags,
+    gst_segment_do_seek (&seeksegment, rate, format, flags,
         cur_type, cur, stop_type, stop, &update);
   }
 
@@ -1374,32 +1397,8 @@ gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
 
   /* prepare for streaming again */
   if (flush) {
-    gst_pad_push_event (qtdemux->sinkpad, gst_event_new_flush_stop ());
-    gst_qtdemux_push_event (qtdemux, gst_event_new_flush_stop ());
-  } else if (qtdemux->segment_running) {
-    /* we are running the current segment and doing a non-flushing seek,
-     * close the segment first based on the last_stop. */
-    GST_DEBUG_OBJECT (qtdemux, "closing running segment %" G_GINT64_FORMAT
-        " to %" G_GINT64_FORMAT, qtdemux->segment.start,
-        qtdemux->segment.last_stop);
-
-    if (qtdemux->segment.rate >= 0) {
-      /* FIXME, rate is the product of the global rate and the (quicktime)
-       * segment rate. */
-      qtdemux->pending_newsegment = gst_event_new_new_segment (TRUE,
-          qtdemux->segment.rate, qtdemux->segment.format,
-          qtdemux->segment.start, qtdemux->segment.last_stop,
-          qtdemux->segment.time);
-    } else {                    /* For Reverse Playback */
-      guint64 stop;
-
-      if ((stop = qtdemux->segment.stop) == -1)
-        stop = qtdemux->segment.duration;
-      /* for reverse playback, we played from stop to last_stop. */
-      qtdemux->pending_newsegment = gst_event_new_new_segment (TRUE,
-          qtdemux->segment.rate, qtdemux->segment.format,
-          qtdemux->segment.last_stop, stop, qtdemux->segment.last_stop);
-    }
+    gst_pad_push_event (qtdemux->sinkpad, gst_event_new_flush_stop (TRUE));
+    gst_qtdemux_push_event (qtdemux, gst_event_new_flush_stop (TRUE));
   }
 
   /* commit the new segment */
@@ -1408,12 +1407,10 @@ gst_qtdemux_do_seek (GstQTDemux * qtdemux, GstPad * pad, GstEvent * event)
   if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
     gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
         gst_message_new_segment_start (GST_OBJECT_CAST (qtdemux),
-            qtdemux->segment.format, qtdemux->segment.last_stop));
+            qtdemux->segment.format, qtdemux->segment.position));
   }
 
-  /* restart streaming, NEWSEGMENT will be sent from the streaming
-   * thread. */
-  qtdemux->segment_running = TRUE;
+  /* restart streaming, NEWSEGMENT will be sent from the streaming thread. */
   for (i = 0; i < qtdemux->n_streams; i++)
     qtdemux->streams[i]->last_ret = GST_FLOW_OK;
 
@@ -1598,24 +1595,16 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
   GST_LOG_OBJECT (demux, "handling %s event", GST_EVENT_TYPE_NAME (event));
 
   switch (GST_EVENT_TYPE (event)) {
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
     {
-      GstFormat format;
-      gdouble rate, arate;
-      gint64 start, stop, time, offset = 0;
+      gint64 offset = 0;
       QtDemuxStream *stream;
       gint idx;
-      gboolean update;
       GstSegment segment;
 
       /* some debug output */
-      gst_segment_init (&segment, GST_FORMAT_UNDEFINED);
-      gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
-          &start, &stop, &time);
-      gst_segment_set_newsegment_full (&segment, update, rate, arate, format,
-          start, stop, time);
-      GST_DEBUG_OBJECT (demux,
-          "received format %d newsegment %" GST_SEGMENT_FORMAT, format,
+      gst_event_copy_segment (event, &segment);
+      GST_DEBUG_OBJECT (demux, "received newsegment %" GST_SEGMENT_FORMAT,
           &segment);
 
       /* chain will send initial newsegment after pads have been added */
@@ -1625,12 +1614,12 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
       }
 
       /* we only expect a BYTE segment, e.g. following a seek */
-      if (format == GST_FORMAT_BYTES) {
-        if (start > 0) {
+      if (segment.format == GST_FORMAT_BYTES) {
+        if (GST_CLOCK_TIME_IS_VALID (segment.start)) {
           gint64 requested_seek_time;
           guint64 seek_offset;
 
-          offset = start;
+          offset = segment.start;
 
           GST_OBJECT_LOCK (demux);
           requested_seek_time = demux->requested_seek_time;
@@ -1640,19 +1629,20 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
           GST_OBJECT_UNLOCK (demux);
 
           if (offset == seek_offset) {
-            start = requested_seek_time;
+            segment.start = requested_seek_time;
           } else {
-            gst_qtdemux_find_sample (demux, start, TRUE, FALSE, NULL, NULL,
-                &start);
-            start = MAX (start, 0);
+            gst_qtdemux_find_sample (demux, segment.start, TRUE, FALSE, NULL,
+                NULL, (gint64 *) & segment.start);
+            if ((gint64) segment.start < 0)
+              segment.start = 0;
           }
         }
-        if (stop > 0) {
-          gst_qtdemux_find_sample (demux, stop, FALSE, FALSE, NULL, NULL,
-              &stop);
+        if (GST_CLOCK_TIME_IS_VALID (segment.stop)) {
+          gst_qtdemux_find_sample (demux, segment.stop, FALSE, FALSE, NULL,
+              NULL, (gint64 *) & segment.stop);
           /* keyframe seeking should already arrange for start >= stop,
            * but make sure in other rare cases */
-          stop = MAX (stop, start);
+          segment.stop = MAX (segment.stop, segment.start);
         }
       } else {
         GST_DEBUG_OBJECT (demux, "unsupported segment format, ignoring");
@@ -1660,16 +1650,14 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
       }
 
       /* accept upstream's notion of segment and distribute along */
-      gst_segment_set_newsegment_full (&demux->segment, update, rate, arate,
-          GST_FORMAT_TIME, start, stop, start);
-      GST_DEBUG_OBJECT (demux, "Pushing newseg update %d, rate %g, "
-          "applied rate %g, format %d, start %" GST_TIME_FORMAT ", "
-          "stop %" GST_TIME_FORMAT, update, rate, arate, GST_FORMAT_TIME,
-          GST_TIME_ARGS (start), GST_TIME_ARGS (stop));
+      segment.time = segment.start;
+      segment.duration = demux->segment.duration;
+      segment.base = gst_segment_to_running_time (&demux->segment,
+          GST_FORMAT_TIME, demux->segment.position);
 
-      gst_qtdemux_push_event (demux,
-          gst_event_new_new_segment_full (update, rate, arate, GST_FORMAT_TIME,
-              start, stop, start));
+      gst_segment_copy_into (&segment, &demux->segment);
+      GST_DEBUG_OBJECT (demux, "Pushing newseg %" GST_SEGMENT_FORMAT, &segment);
+      gst_qtdemux_push_event (demux, gst_event_new_segment (&segment));
 
       /* clear leftover in current segment, if any */
       gst_adapter_clear (demux->adapter);
@@ -1693,6 +1681,7 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
     case GST_EVENT_FLUSH_STOP:
     {
       gint i;
+      GstClockTime dur;
 
       /* clean up, force EOS if no more info follows */
       gst_adapter_clear (demux->adapter);
@@ -1703,6 +1692,9 @@ gst_qtdemux_handle_sink_event (GstPad * sinkpad, GstEvent * event)
         demux->streams[i]->last_ret = GST_FLOW_OK;
         demux->streams[i]->sent_eos = FALSE;
       }
+      dur = demux->segment.duration;
+      gst_segment_init (&demux->segment, GST_FORMAT_TIME);
+      demux->segment.duration = dur;
       break;
     }
     case GST_EVENT_EOS:
@@ -1901,7 +1893,7 @@ qtdemux_parse_ftyp (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
     GST_DEBUG_OBJECT (qtdemux, "major brand: %" GST_FOURCC_FORMAT,
         GST_FOURCC_ARGS (qtdemux->major_brand));
     buf = qtdemux->comp_brands = gst_buffer_new_and_alloc (length - 16);
-    memcpy (GST_BUFFER_DATA (buf), buffer + 16, GST_BUFFER_SIZE (buf));
+    _gst_buffer_copy_into_mem (buf, buffer + 16, 0, length - 16);
   }
 }
 
@@ -1947,10 +1939,8 @@ qtdemux_parse_uuid (GstQTDemux * qtdemux, const guint8 * buffer, gint length)
     GstBuffer *buf;
     GstTagList *taglist;
 
-    buf = gst_buffer_new ();
-    GST_BUFFER_DATA (buf) = (guint8 *) buffer + offset + 16;
-    GST_BUFFER_SIZE (buf) = length - offset - 16;
-
+    buf = _gst_buffer_new_wrapped ((guint8 *) buffer + offset + 16,
+        length - offset - 16, NULL);
     taglist = gst_tag_list_from_xmp_buffer (buf);
     gst_buffer_unref (buf);
 
@@ -2105,6 +2095,14 @@ qtdemux_parse_trun (GstQTDemux * qtdemux, GstByteReader * trun,
       stream->track_id, d_sample_duration, d_sample_size, d_sample_flags,
       *base_offset);
 
+  /* presence of stss or not can't really tell us much,
+   * and flags and so on tend to be marginally reliable in these files */
+  if (stream->subtype == FOURCC_soun) {
+    GST_DEBUG_OBJECT (qtdemux,
+        "sound track in fragmented file; marking all keyframes");
+    stream->all_keyframe = TRUE;
+  }
+
   if (!gst_byte_reader_skip (trun, 1) ||
       !gst_byte_reader_get_uint24_be (trun, &flags))
     goto fail;
@@ -2640,13 +2638,16 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
   GstBuffer *buf = NULL;
   GstFlowReturn ret = GST_FLOW_OK;
   guint64 cur_offset = qtdemux->offset;
+  guint8 *data;
+  gsize size;
 
   ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, 16, &buf);
   if (G_UNLIKELY (ret != GST_FLOW_OK))
     goto beach;
-  if (G_LIKELY (GST_BUFFER_SIZE (buf) >= 8))
-    extract_initial_length_and_fourcc (GST_BUFFER_DATA (buf),
-        GST_BUFFER_SIZE (buf), &length, &fourcc);
+  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+  if (G_LIKELY (size >= 8))
+    extract_initial_length_and_fourcc (data, size, &length, &fourcc);
+  gst_buffer_unmap (buf, data, size);
   gst_buffer_unref (buf);
 
   /* maybe we already got most we needed, so only consider this eof */
@@ -2691,51 +2692,48 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
       ret = gst_pad_pull_range (qtdemux->sinkpad, cur_offset, length, &moov);
       if (ret != GST_FLOW_OK)
         goto beach;
-      if (length != GST_BUFFER_SIZE (moov)) {
+      data = gst_buffer_map (moov, &size, NULL, GST_MAP_READ);
+      if (length != size) {
         /* Some files have a 'moov' atom at the end of the file which contains
          * a terminal 'free' atom where the body of the atom is missing.
          * Check for, and permit, this special case.
          */
-        if (GST_BUFFER_SIZE (moov) >= 8) {
-          guint8 *final_data = GST_BUFFER_DATA (moov) +
-              (GST_BUFFER_SIZE (moov) - 8);
+        if (size >= 8) {
+          guint8 *final_data = data + (size - 8);
           guint32 final_length = QT_UINT32 (final_data);
           guint32 final_fourcc = QT_FOURCC (final_data + 4);
-          if (final_fourcc == FOURCC_free &&
-              GST_BUFFER_SIZE (moov) + final_length - 8 == length) {
+          gst_buffer_unmap (moov, data, size);
+          if (final_fourcc == FOURCC_free && size + final_length - 8 == length) {
             /* Ok, we've found that special case. Allocate a new buffer with
              * that free atom actually present. */
             GstBuffer *newmoov = gst_buffer_new_and_alloc (length);
-            gst_buffer_copy_metadata (newmoov, moov,
-                GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS |
-                GST_BUFFER_COPY_CAPS);
-            memcpy (GST_BUFFER_DATA (newmoov), GST_BUFFER_DATA (moov),
-                GST_BUFFER_SIZE (moov));
-            memset (GST_BUFFER_DATA (newmoov) + GST_BUFFER_SIZE (moov), 0,
-                final_length - 8);
+            gst_buffer_copy_into (newmoov, moov, 0, 0, size);
+            data = gst_buffer_map (newmoov, &size, NULL, GST_MAP_WRITE);
+            memset (data + length - final_length + 8, 0, final_length - 8);
             gst_buffer_unref (moov);
             moov = newmoov;
           }
         }
       }
 
-      if (length != GST_BUFFER_SIZE (moov)) {
+      if (length != size) {
         GST_ELEMENT_ERROR (qtdemux, STREAM, DEMUX,
             (_("This file is incomplete and cannot be played.")),
             ("We got less than expected (received %u, wanted %u, offset %"
-                G_GUINT64_FORMAT ")",
-                GST_BUFFER_SIZE (moov), (guint) length, cur_offset));
+                G_GUINT64_FORMAT ")", size, (guint) length, cur_offset));
+        gst_buffer_unmap (moov, data, size);
         gst_buffer_unref (moov);
         ret = GST_FLOW_ERROR;
         goto beach;
       }
       qtdemux->offset += length;
 
-      qtdemux_parse_moov (qtdemux, GST_BUFFER_DATA (moov), length);
+      qtdemux_parse_moov (qtdemux, data, length);
       qtdemux_node_dump (qtdemux, qtdemux->moov_node);
 
       qtdemux_parse_tree (qtdemux);
       g_node_destroy (qtdemux->moov_node);
+      gst_buffer_unmap (moov, data, size);
       gst_buffer_unref (moov);
       qtdemux->moov_node = NULL;
       qtdemux->got_moov = TRUE;
@@ -2751,8 +2749,9 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
       if (ret != GST_FLOW_OK)
         goto beach;
       qtdemux->offset += length;
-      qtdemux_parse_ftyp (qtdemux, GST_BUFFER_DATA (ftyp),
-          GST_BUFFER_SIZE (ftyp));
+      data = gst_buffer_map (ftyp, &size, NULL, GST_MAP_READ);
+      qtdemux_parse_ftyp (qtdemux, data, size);
+      gst_buffer_unmap (ftyp, data, size);
       gst_buffer_unref (ftyp);
       break;
     }
@@ -2765,8 +2764,9 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
       if (ret != GST_FLOW_OK)
         goto beach;
       qtdemux->offset += length;
-      qtdemux_parse_uuid (qtdemux, GST_BUFFER_DATA (uuid),
-          GST_BUFFER_SIZE (uuid));
+      data = gst_buffer_map (uuid, &size, NULL, GST_MAP_READ);
+      qtdemux_parse_uuid (qtdemux, data, size);
+      gst_buffer_unmap (uuid, data, size);
       gst_buffer_unref (uuid);
       break;
     }
@@ -2781,8 +2781,9 @@ gst_qtdemux_loop_state_header (GstQTDemux * qtdemux)
       ret = gst_qtdemux_pull_atom (qtdemux, cur_offset, length, &unknown);
       if (ret != GST_FLOW_OK)
         goto beach;
-      GST_MEMDUMP ("Unknown tag", GST_BUFFER_DATA (unknown),
-          GST_BUFFER_SIZE (unknown));
+      data = gst_buffer_map (unknown, &size, NULL, GST_MAP_READ);
+      GST_MEMDUMP ("Unknown tag", data, size);
+      gst_buffer_unmap (unknown, data, size);
       gst_buffer_unref (unknown);
       qtdemux->offset += length;
       break;
@@ -2827,7 +2828,7 @@ gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
     QtDemuxStream *str = qtdemux->streams[n];
 
     seg_idx = gst_qtdemux_find_segment (qtdemux, str,
-        qtdemux->segment.last_stop);
+        qtdemux->segment.position);
 
     /* segment not found, continue with normal flow */
     if (seg_idx == -1)
@@ -2903,7 +2904,7 @@ gst_qtdemux_seek_to_previous_keyframe (GstQTDemux * qtdemux)
       k_index, GST_TIME_ARGS (k_pos));
 
   /* Set last_stop with the keyframe timestamp we pushed of that stream */
-  gst_segment_set_last_stop (&qtdemux->segment, GST_FORMAT_TIME, last_stop);
+  qtdemux->segment.position = last_stop;
   GST_DEBUG_OBJECT (qtdemux, "last_stop now is %" GST_TIME_FORMAT,
       GST_TIME_ARGS (last_stop));
 
@@ -3067,13 +3068,18 @@ gst_qtdemux_activate_segment (GstQTDemux * qtdemux, QtDemuxStream * stream,
 
   /* update the segment values used for clipping */
   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
-  gst_segment_set_newsegment (&stream->segment, FALSE, rate, GST_FORMAT_TIME,
-      start, stop, time);
+  /* accumulate previous segments */
+  if (GST_CLOCK_TIME_IS_VALID (stream->segment.stop))
+    stream->segment.base += (stream->segment.stop - stream->segment.start) /
+        ABS (stream->segment.rate);
+  stream->segment.rate = rate;
+  stream->segment.start = start;
+  stream->segment.stop = stop;
+  stream->segment.time = time;
 
   /* now prepare and send the segment */
   if (stream->pad) {
-    event = gst_event_new_new_segment (FALSE, rate, GST_FORMAT_TIME,
-        start, stop, time);
+    event = gst_event_new_segment (&stream->segment);
     gst_pad_push_event (stream->pad, event);
     /* assume we can send more data now */
     stream->last_ret = GST_FLOW_OK;
@@ -3335,8 +3341,8 @@ gst_qtdemux_sync_streams (GstQTDemux * demux)
     end_time = stream->segments[stream->n_segments - 1].stop_time;
     GST_LOG_OBJECT (demux, "current position: %" GST_TIME_FORMAT
         ", stream end: %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (demux->segment.last_stop), GST_TIME_ARGS (end_time));
-    if (end_time + 2 * GST_SECOND < demux->segment.last_stop) {
+        GST_TIME_ARGS (demux->segment.position), GST_TIME_ARGS (end_time));
+    if (end_time + 2 * GST_SECOND < demux->segment.position) {
       GST_DEBUG_OBJECT (demux, "sending EOS for stream %s",
           GST_PAD_NAME (stream->pad));
       stream->sent_eos = TRUE;
@@ -3397,16 +3403,16 @@ static GstBuffer *
 gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
     GstBuffer * buf)
 {
-  gint64 start, stop, cstart, cstop, diff;
+  guint64 start, stop, cstart, cstop, diff;
   GstClockTime timestamp = GST_CLOCK_TIME_NONE, duration = GST_CLOCK_TIME_NONE;
-  guint8 *data;
   guint size;
   gint num_rate, denom_rate;
   gint frame_size;
   gboolean clip_data;
+  guint offset;
 
-  data = GST_BUFFER_DATA (buf);
-  size = GST_BUFFER_SIZE (buf);
+  size = gst_buffer_get_size (buf);
+  offset = 0;
 
   /* depending on the type, setup the clip parameters */
   if (stream->subtype == FOURCC_soun) {
@@ -3456,7 +3462,7 @@ gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
           "clipping start to %" GST_TIME_FORMAT " %"
           G_GUINT64_FORMAT " bytes", GST_TIME_ARGS (cstart), diff);
 
-      data += diff;
+      offset = diff;
       size -= diff;
     }
   }
@@ -3475,10 +3481,9 @@ gst_qtdemux_clip_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
     }
   }
 
+  gst_buffer_resize (buf, offset, size);
   GST_BUFFER_TIMESTAMP (buf) = timestamp;
   GST_BUFFER_DURATION (buf) = duration;
-  GST_BUFFER_SIZE (buf) = size;
-  GST_BUFFER_DATA (buf) = data;
 
   return buf;
 
@@ -3508,12 +3513,10 @@ gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
     GstBuffer * buf)
 {
   guint8 *data;
-  guint size, nsize = 0;
+  guint nsize = 0;
+  gsize size;
   gchar *str;
 
-  data = GST_BUFFER_DATA (buf);
-  size = GST_BUFFER_SIZE (buf);
-
   /* not many cases for now */
   if (G_UNLIKELY (stream->fourcc == FOURCC_mp4s)) {
     /* send a one time dvd clut event */
@@ -3528,6 +3531,8 @@ gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
     return buf;
   }
 
+  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+
   if (G_LIKELY (size >= 2)) {
     nsize = GST_READ_UINT16_BE (data);
     nsize = MIN (nsize, size - 2);
@@ -3538,15 +3543,13 @@ gst_qtdemux_process_buffer (GstQTDemux * qtdemux, QtDemuxStream * stream,
   /* takes care of UTF-8 validation or UTF-16 recognition,
    * no other encoding expected */
   str = gst_tag_freeform_string_to_utf8 ((gchar *) data + 2, nsize, NULL);
+  gst_buffer_unmap (buf, data, size);
   if (str) {
     gst_buffer_unref (buf);
-    buf = gst_buffer_new ();
-    GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = (guint8 *) str;
-    GST_BUFFER_SIZE (buf) = strlen (str);
+    buf = _gst_buffer_new_wrapped (str, strlen (str), g_free);
   } else {
     /* may be 0-size subtitle, which is also sent to keep pipeline going */
-    GST_BUFFER_DATA (buf) = data + 2;
-    GST_BUFFER_SIZE (buf) = nsize;
+    gst_buffer_resize (buf, 2, nsize);
   }
 
   /* FIXME ? convert optional subsequent style info to markup */
@@ -3568,8 +3571,12 @@ gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
 
   if (G_UNLIKELY (stream->fourcc == FOURCC_rtsp)) {
     gchar *url;
+    guint8 *bdata;
+    gsize bsize;
 
-    url = g_strndup ((gchar *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
+    bdata = gst_buffer_map (buf, &bsize, NULL, GST_MAP_READ);
+    url = g_strndup ((gchar *) bdata, bsize);
+    gst_buffer_unmap (buf, bdata, bsize);
     if (url != NULL && strlen (url) != 0) {
       /* we have RTSP redirect now */
       gst_element_post_message (GST_ELEMENT_CAST (qtdemux),
@@ -3586,7 +3593,7 @@ gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
 
   /* position reporting */
   if (qtdemux->segment.rate >= 0) {
-    gst_segment_set_last_stop (&qtdemux->segment, GST_FORMAT_TIME, position);
+    qtdemux->segment.position = position;
     gst_qtdemux_sync_streams (qtdemux);
   }
 
@@ -3605,7 +3612,6 @@ gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
       GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
       stream->discont = FALSE;
     }
-    gst_buffer_set_caps (buffer, stream->caps);
 
     gst_pad_push (stream->pad, buffer);
 
@@ -3613,7 +3619,7 @@ gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
   }
 
   /* we're going to modify the metadata */
-  buf = gst_buffer_make_metadata_writable (buf);
+  buf = gst_buffer_make_writable (buf);
 
   if (G_UNLIKELY (stream->need_process))
     buf = gst_qtdemux_process_buffer (qtdemux, stream, buf);
@@ -3624,8 +3630,7 @@ gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
   GST_BUFFER_OFFSET_END (buf) = -1;
 
   if (G_UNLIKELY (stream->padding)) {
-    GST_BUFFER_DATA (buf) += stream->padding;
-    GST_BUFFER_SIZE (buf) -= stream->padding;
+    gst_buffer_resize (buf, stream->padding, -1);
   }
 
   if (G_UNLIKELY (qtdemux->element_index)) {
@@ -3661,8 +3666,6 @@ gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux,
   if (!keyframe)
     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
 
-  gst_buffer_set_caps (buf, stream->caps);
-
   GST_LOG_OBJECT (qtdemux,
       "Pushing buffer with time %" GST_TIME_FORMAT ", duration %"
       GST_TIME_FORMAT " on pad %s", GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
@@ -3821,7 +3824,6 @@ invalid_state:
   {
     GST_ELEMENT_ERROR (qtdemux, STREAM, FAILED,
         (NULL), ("streaming stopped, invalid state"));
-    qtdemux->segment_running = FALSE;
     gst_pad_pause_task (pad);
     gst_qtdemux_push_event (qtdemux, gst_event_new_eos ());
     goto done;
@@ -3832,7 +3834,6 @@ pause:
 
     GST_LOG_OBJECT (qtdemux, "pausing task, reason %s", reason);
 
-    qtdemux->segment_running = FALSE;
     gst_pad_pause_task (pad);
 
     /* fatal errors need special actions */
@@ -3845,11 +3846,6 @@ pause:
       if (qtdemux->segment.flags & GST_SEEK_FLAG_SEGMENT) {
         gint64 stop;
 
-        /* FIXME: I am not sure this is the right fix. If the sinks are
-         * supposed to detect the segment is complete and accumulate
-         * automatically, it does not seem to work here. Need more work */
-        qtdemux->segment_running = TRUE;
-
         if ((stop = qtdemux->segment.stop) == -1)
           stop = qtdemux->segment.duration;
 
@@ -3996,10 +3992,8 @@ gst_qtdemux_check_seekability (GstQTDemux * demux)
 
   /* try harder to query upstream size if we didn't get it the first time */
   if (seekable && stop == -1) {
-    GstFormat fmt = GST_FORMAT_BYTES;
-
     GST_DEBUG_OBJECT (demux, "doing duration query to fix up unset stop");
-    gst_pad_query_peer_duration (demux->sinkpad, &fmt, &stop);
+    gst_pad_query_peer_duration (demux->sinkpad, GST_FORMAT_BYTES, &stop);
   }
 
   /* if upstream doesn't know the size, it's likely that it's not seekable in
@@ -4051,11 +4045,13 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
 
         gst_qtdemux_check_seekability (demux);
 
-        data = gst_adapter_peek (demux->adapter, demux->neededbytes);
+        data = gst_adapter_map (demux->adapter, demux->neededbytes);
 
         /* get fourcc/length, set neededbytes */
         extract_initial_length_and_fourcc ((guint8 *) data, demux->neededbytes,
             &size, &fourcc);
+        gst_adapter_unmap (demux->adapter, 0);
+        data = NULL;
         GST_DEBUG_OBJECT (demux, "Peeking found [%" GST_FOURCC_FORMAT "] "
             "size: %" G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), size);
         if (size == 0) {
@@ -4117,7 +4113,7 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
               /* there may be multiple mdat (or alike) buffers */
               /* sanity check */
               if (demux->mdatbuffer)
-                bs = GST_BUFFER_SIZE (demux->mdatbuffer);
+                bs = gst_buffer_get_size (demux->mdatbuffer);
               else
                 bs = 0;
               if (size + bs > 10 * (1 << 20))
@@ -4151,7 +4147,7 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
 
         GST_DEBUG_OBJECT (demux, "In header");
 
-        data = gst_adapter_peek (demux->adapter, demux->neededbytes);
+        data = gst_adapter_map (demux->adapter, demux->neededbytes);
 
         /* parse the header */
         extract_initial_length_and_fourcc (data, demux->neededbytes, NULL,
@@ -4162,11 +4158,8 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
           demux->got_moov = TRUE;
 
           /* prepare newsegment to send when streaming actually starts */
-          if (!demux->pending_newsegment) {
-            demux->pending_newsegment =
-                gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
-                0, GST_CLOCK_TIME_NONE, 0);
-          }
+          if (!demux->pending_newsegment)
+            demux->pending_newsegment = gst_event_new_segment (&demux->segment);
 
           qtdemux_parse_moov (demux, data, demux->neededbytes);
           qtdemux_node_dump (demux, demux->moov_node);
@@ -4181,6 +4174,7 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
             GST_DEBUG_OBJECT (demux, "Parsing [moof]");
             if (!qtdemux_parse_moof (demux, data, demux->neededbytes,
                     demux->offset, NULL)) {
+              gst_adapter_unmap (demux->adapter, 0);
               ret = GST_FLOW_ERROR;
               goto done;
             }
@@ -4199,6 +4193,8 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
               GST_FOURCC_ARGS (fourcc));
           /* Let's jump that one and go back to initial state */
         }
+        gst_adapter_unmap (demux->adapter, 0);
+        data = NULL;
 
         if (demux->mdatbuffer && demux->n_streams) {
           /* the mdat was before the header */
@@ -4243,12 +4239,14 @@ gst_qtdemux_chain (GstPad * sinkpad, GstBuffer * inbuf)
       }
       case QTDEMUX_STATE_BUFFER_MDAT:{
         GstBuffer *buf;
+        guint8 fourcc[4];
 
         GST_DEBUG_OBJECT (demux, "Got our buffer at offset %" G_GUINT64_FORMAT,
             demux->offset);
         buf = gst_adapter_take_buffer (demux->adapter, demux->neededbytes);
+        gst_buffer_extract (buf, 0, fourcc, 4);
         GST_DEBUG_OBJECT (demux, "mdatbuffer starts with %" GST_FOURCC_FORMAT,
-            GST_FOURCC_ARGS (QT_FOURCC (GST_BUFFER_DATA (buf) + 4)));
+            GST_FOURCC_ARGS (QT_FOURCC (fourcc)));
         if (demux->mdatbuffer)
           demux->mdatbuffer = gst_buffer_join (demux->mdatbuffer, buf);
         else
@@ -4424,10 +4422,30 @@ no_moov:
 static gboolean
 qtdemux_sink_activate (GstPad * sinkpad)
 {
-  if (gst_pad_check_pull_range (sinkpad))
-    return gst_pad_activate_pull (sinkpad, TRUE);
-  else
+  GstQuery *query;
+  gboolean pull_mode;
+
+  query = gst_query_new_scheduling ();
+
+  if (!gst_pad_peer_query (sinkpad, query)) {
+    gst_query_unref (query);
+    goto activate_push;
+  }
+
+  gst_query_parse_scheduling (query, &pull_mode, NULL, NULL, NULL, NULL, NULL);
+  gst_query_unref (query);
+
+  if (!pull_mode)
+    goto activate_push;
+
+  GST_DEBUG_OBJECT (sinkpad, "activating pull");
+  return gst_pad_activate_pull (sinkpad, TRUE);
+
+activate_push:
+  {
+    GST_DEBUG_OBJECT (sinkpad, "activating push");
     return gst_pad_activate_push (sinkpad, TRUE);
+  }
 }
 
 static gboolean
@@ -4437,11 +4455,9 @@ qtdemux_sink_activate_pull (GstPad * sinkpad, gboolean active)
 
   if (active) {
     demux->pullbased = TRUE;
-    demux->segment_running = TRUE;
     return gst_pad_start_task (sinkpad, (GstTaskFunction) gst_qtdemux_loop,
         sinkpad);
   } else {
-    demux->segment_running = FALSE;
     return gst_pad_stop_task (sinkpad);
   }
 }
@@ -4641,19 +4657,19 @@ qtdemux_parse_theora_extension (GstQTDemux * qtdemux, QtDemuxStream * stream,
     switch (type) {
       case FOURCC_tCtH:
         buffer = gst_buffer_new_and_alloc (size);
-        memcpy (GST_BUFFER_DATA (buffer), buf, size);
+        _gst_buffer_copy_into_mem (buffer, buf, 0, size);
         stream->buffers = g_slist_append (stream->buffers, buffer);
         GST_LOG_OBJECT (qtdemux, "parsing theora header");
         break;
       case FOURCC_tCt_:
         buffer = gst_buffer_new_and_alloc (size);
-        memcpy (GST_BUFFER_DATA (buffer), buf, size);
+        _gst_buffer_copy_into_mem (buffer, buf, 0, size);
         stream->buffers = g_slist_append (stream->buffers, buffer);
         GST_LOG_OBJECT (qtdemux, "parsing theora comment");
         break;
       case FOURCC_tCtC:
         buffer = gst_buffer_new_and_alloc (size);
-        memcpy (GST_BUFFER_DATA (buffer), buf, size);
+        _gst_buffer_copy_into_mem (buffer, buf, 0, size);
         stream->buffers = g_slist_append (stream->buffers, buffer);
         GST_LOG_OBJECT (qtdemux, "parsing theora codebook");
         break;
@@ -4962,11 +4978,9 @@ gst_qtdemux_add_stream (GstQTDemux * qtdemux,
 {
   /* consistent default for push based mode */
   gst_segment_init (&stream->segment, GST_FORMAT_TIME);
-  gst_segment_set_newsegment (&stream->segment, FALSE, 1.0, GST_FORMAT_TIME,
-      0, GST_CLOCK_TIME_NONE, 0);
 
   if (stream->subtype == FOURCC_vide) {
-    gchar *name = g_strdup_printf ("video_%02d", qtdemux->n_video_streams);
+    gchar *name = g_strdup_printf ("video_%u", qtdemux->n_video_streams);
 
     stream->pad =
         gst_pad_new_from_static_template (&gst_qtdemux_videosrc_template, name);
@@ -5066,10 +5080,8 @@ gst_qtdemux_add_stream (GstQTDemux * qtdemux,
 
         /* make sure it's not writable. We leave MALLOCDATA to NULL so that we
          * don't free any of the buffer data. */
-        palette = gst_buffer_new ();
-        GST_BUFFER_FLAG_SET (palette, GST_BUFFER_FLAG_READONLY);
-        GST_BUFFER_DATA (palette) = (guint8 *) palette_data;
-        GST_BUFFER_SIZE (palette) = sizeof (guint32) * palette_count;
+        palette = _gst_buffer_new_wrapped ((gpointer) palette_data,
+            palette_count, NULL);
 
         gst_caps_set_simple (stream->caps, "palette_data",
             GST_TYPE_BUFFER, palette, NULL);
@@ -5084,7 +5096,7 @@ gst_qtdemux_add_stream (GstQTDemux * qtdemux,
     }
     qtdemux->n_video_streams++;
   } else if (stream->subtype == FOURCC_soun) {
-    gchar *name = g_strdup_printf ("audio_%02d", qtdemux->n_audio_streams);
+    gchar *name = g_strdup_printf ("audio_%u", qtdemux->n_audio_streams);
 
     stream->pad =
         gst_pad_new_from_static_template (&gst_qtdemux_audiosrc_template, name);
@@ -5098,7 +5110,7 @@ gst_qtdemux_add_stream (GstQTDemux * qtdemux,
   } else if (stream->subtype == FOURCC_strm) {
     GST_DEBUG_OBJECT (qtdemux, "stream type, not creating pad");
   } else if (stream->subtype == FOURCC_subp || stream->subtype == FOURCC_text) {
-    gchar *name = g_strdup_printf ("subtitle_%02d", qtdemux->n_sub_streams);
+    gchar *name = g_strdup_printf ("subtitle_%u", qtdemux->n_sub_streams);
 
     stream->pad =
         gst_pad_new_from_static_template (&gst_qtdemux_subsrc_template, name);
@@ -5114,8 +5126,6 @@ gst_qtdemux_add_stream (GstQTDemux * qtdemux,
 
     gst_pad_use_fixed_caps (stream->pad);
     gst_pad_set_event_function (stream->pad, gst_qtdemux_handle_src_event);
-    gst_pad_set_query_type_function (stream->pad,
-        gst_qtdemux_get_src_query_types);
     gst_pad_set_query_function (stream->pad, gst_qtdemux_handle_src_query);
 
     GST_DEBUG_OBJECT (qtdemux, "setting caps %" GST_PTR_FORMAT, stream->caps);
@@ -5128,13 +5138,6 @@ gst_qtdemux_add_stream (GstQTDemux * qtdemux,
     if (stream->pending_tags)
       gst_tag_list_free (stream->pending_tags);
     stream->pending_tags = list;
-    if (list) {
-      /* post now, send event on pad later */
-      GST_DEBUG_OBJECT (qtdemux, "Posting tags %" GST_PTR_FORMAT, list);
-      gst_element_post_message (GST_ELEMENT (qtdemux),
-          gst_message_new_tag_full (GST_OBJECT (qtdemux), stream->pad,
-              gst_tag_list_copy (list)));
-    }
     /* global tags go on each pad anyway */
     stream->send_global_tags = TRUE;
   }
@@ -5155,17 +5158,21 @@ qtdemux_find_atom (GstQTDemux * qtdemux, guint64 * offset,
       G_GUINT64_FORMAT, GST_FOURCC_ARGS (fourcc), *offset);
 
   while (TRUE) {
+    guint8 *bdata;
+    gsize bsize;
+
     ret = gst_pad_pull_range (qtdemux->sinkpad, *offset, 16, &buf);
     if (G_UNLIKELY (ret != GST_FLOW_OK))
       goto locate_failed;
-    if (G_LIKELY (GST_BUFFER_SIZE (buf) != 16)) {
+    if (G_UNLIKELY (gst_buffer_get_size (buf) != 16)) {
       /* likely EOF */
       ret = GST_FLOW_UNEXPECTED;
       gst_buffer_unref (buf);
       goto locate_failed;
     }
-    extract_initial_length_and_fourcc (GST_BUFFER_DATA (buf), 16, length,
-        &lfourcc);
+    bdata = gst_buffer_map (buf, &bsize, NULL, GST_MAP_READ);
+    extract_initial_length_and_fourcc (bdata, 16, length, &lfourcc);
+    gst_buffer_unmap (buf, bdata, bsize);
     gst_buffer_unref (buf);
 
     if (G_UNLIKELY (*length == 0)) {
@@ -5204,7 +5211,9 @@ qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
   guint64 length, offset;
   GstBuffer *buf = NULL;
   GstFlowReturn ret = GST_FLOW_OK;
-  GstFlowReturn res = TRUE;
+  GstFlowReturn res = GST_FLOW_OK;
+  guint8 *bdata;
+  gsize bsize;
 
   offset = qtdemux->moof_offset;
   GST_DEBUG_OBJECT (qtdemux, "next moof at offset %" G_GUINT64_FORMAT, offset);
@@ -5224,13 +5233,15 @@ qtdemux_add_fragmented_samples (GstQTDemux * qtdemux)
   ret = gst_qtdemux_pull_atom (qtdemux, offset, length, &buf);
   if (G_UNLIKELY (ret != GST_FLOW_OK))
     goto flow_failed;
-  if (!qtdemux_parse_moof (qtdemux, GST_BUFFER_DATA (buf),
-          GST_BUFFER_SIZE (buf), offset, NULL)) {
+  bdata = gst_buffer_map (buf, &bsize, NULL, GST_MAP_READ);
+  if (!qtdemux_parse_moof (qtdemux, bdata, bsize, offset, NULL)) {
+    gst_buffer_unmap (buf, bdata, bsize);
     gst_buffer_unref (buf);
     buf = NULL;
     goto parse_failed;
   }
 
+  gst_buffer_unmap (buf, bdata, bsize);
   gst_buffer_unref (buf);
   buf = NULL;
 
@@ -6069,7 +6080,7 @@ qtdemux_parse_svq3_stsd_data (GstQTDemux * qtdemux, GNode * stsd,
                 seqh_size = QT_UINT32 (data + 4);
                 if (seqh_size > 0) {
                   _seqh = gst_buffer_new_and_alloc (seqh_size);
-                  memcpy (GST_BUFFER_DATA (_seqh), data + 8, seqh_size);
+                  _gst_buffer_copy_into_mem (_seqh, data + 8, 0, seqh_size);
                 }
               }
             }
@@ -6226,11 +6237,13 @@ qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
   static const guint wb_bitrates[] = {
     6600, 8850, 12650, 14250, 15850, 18250, 19850, 23050, 23850
   };
-  const guint8 *data = GST_BUFFER_DATA (buf);
-  guint size = QT_UINT32 (data), max_mode;
+  guint8 *data;
+  gsize size, max_mode;
   guint16 mode_set;
 
-  if (GST_BUFFER_SIZE (buf) != 0x11) {
+  data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
+
+  if (size != 0x11) {
     GST_DEBUG ("Atom should have size 0x11, not %u", size);
     goto bad_data;
   }
@@ -6255,9 +6268,11 @@ qtdemux_parse_amr_bitrate (GstBuffer * buf, gboolean wb)
     goto bad_data;
   }
 
+  gst_buffer_unmap (buf, data, size);
   return wb ? wb_bitrates[max_mode] : nb_bitrates[max_mode];
 
 bad_data:
+  gst_buffer_unmap (buf, data, size);
   return 0;
 }
 
@@ -6462,7 +6477,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
     stream->caps =
         qtdemux_video_caps (qtdemux, stream, fourcc, stsd_data, &codec);
     if (codec) {
-      list = gst_tag_list_new ();
+      list = gst_tag_list_new_empty ();
       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
           GST_TAG_VIDEO_CODEC, codec, NULL);
       g_free (codec);
@@ -6525,7 +6540,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
                     avc_data + 8 + 1, size - 1);
 
                 buf = gst_buffer_new_and_alloc (size);
-                memcpy (GST_BUFFER_DATA (buf), avc_data + 0x8, size);
+                _gst_buffer_copy_into_mem (buf, avc_data + 0x8, 0, size);
                 gst_caps_set_simple (stream->caps,
                     "codec_data", GST_TYPE_BUFFER, buf, NULL);
                 gst_buffer_unref (buf);
@@ -6556,7 +6571,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
                 }
 
                 if (!list)
-                  list = gst_tag_list_new ();
+                  list = gst_tag_list_new_empty ();
 
                 if (max_bitrate > 0 && max_bitrate < G_MAXUINT32) {
                   gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
@@ -6604,7 +6619,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
             if (len > 0x8) {
               len -= 0x8;
               buf = gst_buffer_new_and_alloc (len);
-              memcpy (GST_BUFFER_DATA (buf), data + 8, len);
+              _gst_buffer_copy_into_mem (buf, data + 8, 0, len);
               gst_caps_set_simple (stream->caps,
                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
               gst_buffer_unref (buf);
@@ -6617,7 +6632,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
           /* see annex I of the jpeg2000 spec */
           GNode *jp2h, *ihdr, *colr, *mjp2, *field, *prefix, *cmap, *cdef;
           const guint8 *data;
-          guint32 fourcc = 0;
+          const gchar *colorspace;
           gint ncomp = 0;
           guint32 ncomp_map = 0;
           gint32 *comp_map = NULL;
@@ -6648,21 +6663,22 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
           if (QT_UINT8 ((guint8 *) colr->data + 8) == 1) {
             switch (QT_UINT32 ((guint8 *) colr->data + 11)) {
               case 16:
-                fourcc = GST_MAKE_FOURCC ('s', 'R', 'G', 'B');
+                colorspace = "sRGB";
                 break;
               case 17:
-                fourcc = GST_MAKE_FOURCC ('G', 'R', 'A', 'Y');
+                colorspace = "GRAY";
                 break;
               case 18:
-                fourcc = GST_MAKE_FOURCC ('s', 'Y', 'U', 'V');
+                colorspace = "sYUV";
                 break;
               default:
+                colorspace = NULL;
                 break;
             }
           }
-          if (!fourcc)
+          if (!colorspace)
             /* colr is required, and only values 16, 17, and 18 are specified,
-               so error if we have no fourcc */
+               so error if we have no colorspace */
             break;
 
           /* extract component mapping */
@@ -6729,7 +6745,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
           gst_caps_set_simple (stream->caps,
               "num-components", G_TYPE_INT, ncomp, NULL);
           gst_caps_set_simple (stream->caps,
-              "fourcc", GST_TYPE_FOURCC, fourcc, NULL);
+              "colorspace", G_TYPE_STRING, colorspace, NULL);
 
           if (comp_map) {
             GValue arr = { 0, };
@@ -6787,7 +6803,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
             if (len > 0x8) {
               len -= 0x8;
               buf = gst_buffer_new_and_alloc (len);
-              memcpy (GST_BUFFER_DATA (buf), data + 8, len);
+              _gst_buffer_copy_into_mem (buf, data + 8, 0, len);
               gst_caps_set_simple (stream->caps,
                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
               gst_buffer_unref (buf);
@@ -6817,7 +6833,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
 
           GST_DEBUG_OBJECT (qtdemux, "found codec_data in stsd");
           buf = gst_buffer_new_and_alloc (len);
-          memcpy (GST_BUFFER_DATA (buf), stsd_data, len);
+          _gst_buffer_copy_into_mem (buf, stsd_data, 0, len);
           gst_caps_set_simple (stream->caps,
               "codec_data", GST_TYPE_BUFFER, buf, NULL);
           gst_buffer_unref (buf);
@@ -6851,7 +6867,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
         case FOURCC_ovc1:
         {
           GNode *ovc1;
-          gchar *ovc1_data;
+          guint8 *ovc1_data;
           guint ovc1_len;
           GstBuffer *buf;
 
@@ -6866,7 +6882,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
             break;
           }
           buf = gst_buffer_new_and_alloc (ovc1_len - 198);
-          memcpy (GST_BUFFER_DATA (buf), ovc1_data + 198, ovc1_len - 198);
+          _gst_buffer_copy_into_mem (buf, ovc1_data + 198, 0, ovc1_len - 198);
           gst_caps_set_simple (stream->caps,
               "codec_data", GST_TYPE_BUFFER, buf, NULL);
           gst_buffer_unref (buf);
@@ -7041,14 +7057,15 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
         }
         if (enda) {
           gst_caps_set_simple (stream->caps,
-              "endianness", G_TYPE_INT, G_LITTLE_ENDIAN, NULL);
+              "format", G_TYPE_STRING, "S24_3LE", NULL);
         }
         break;
       }
       case FOURCC_owma:
       {
         GNode *owma;
-        const gchar *owma_data, *codec_name = NULL;
+        const guint8 *owma_data;
+        const gchar *codec_name = NULL;
         guint owma_len;
         GstBuffer *buf;
         gint version = 1;
@@ -7079,7 +7096,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
         }
         wfex = (WAVEFORMATEX *) (owma_data + 36);
         buf = gst_buffer_new_and_alloc (owma_len - 54);
-        memcpy (GST_BUFFER_DATA (buf), owma_data + 54, owma_len - 54);
+        _gst_buffer_copy_into_mem (buf, owma_data + 54, 0, owma_len - 54);
         if (wfex->wFormatTag == 0x0161) {
           codec_name = "Windows Media Audio";
           version = 2;
@@ -7117,7 +7134,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
       GstStructure *s;
       gint bitrate = 0;
 
-      list = gst_tag_list_new ();
+      list = gst_tag_list_new_empty ();
       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
           GST_TAG_AUDIO_CODEC, codec, NULL);
       g_free (codec);
@@ -7177,9 +7194,8 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
               waveheader += 8;
               headerlen -= 8;
 
-              headerbuf = gst_buffer_new ();
-              GST_BUFFER_DATA (headerbuf) = (guint8 *) waveheader;
-              GST_BUFFER_SIZE (headerbuf) = headerlen;
+              headerbuf = gst_buffer_new_and_alloc (headerlen);
+              _gst_buffer_copy_into_mem (headerbuf, waveheader, 0, headerlen);
 
               if (gst_riff_parse_strf_auds (GST_ELEMENT_CAST (qtdemux),
                       headerbuf, &header, &extra)) {
@@ -7217,7 +7233,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
           if (len > 0x4C) {
             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x4C);
 
-            memcpy (GST_BUFFER_DATA (buf), stsd_data + 0x4C, len - 0x4C);
+            _gst_buffer_copy_into_mem (buf, stsd_data + 0x4C, 0, len - 0x4C);
             gst_caps_set_simple (stream->caps,
                 "codec_data", GST_TYPE_BUFFER, buf, NULL);
             gst_buffer_unref (buf);
@@ -7252,7 +7268,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
               /* codec-data contains alac atom size and prefix,
                * ffmpeg likes it that way, not quite gst-ish though ...*/
               buf = gst_buffer_new_and_alloc (len);
-              memcpy (GST_BUFFER_DATA (buf), alac->data, len);
+              _gst_buffer_copy_into_mem (buf, alac->data, 0, len);
               gst_caps_set_simple (stream->caps,
                   "codec_data", GST_TYPE_BUFFER, buf, NULL);
               gst_buffer_unref (buf);
@@ -7273,14 +7289,14 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
             GstBuffer *buf = gst_buffer_new_and_alloc (len - 0x34);
             guint bitrate;
 
-            memcpy (GST_BUFFER_DATA (buf), stsd_data + 0x34, len - 0x34);
+            _gst_buffer_copy_into_mem (buf, stsd_data + 0x34, 0, len - 0x34);
 
             /* If we have enough data, let's try to get the 'damr' atom. See
              * the 3GPP container spec (26.244) for more details. */
             if ((len - 0x34) > 8 &&
                 (bitrate = qtdemux_parse_amr_bitrate (buf, amrwb))) {
               if (!list)
-                list = gst_tag_list_new ();
+                list = gst_tag_list_new_empty ();
               gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
                   GST_TAG_MAXIMUM_BITRATE, bitrate, NULL);
             }
@@ -7317,7 +7333,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
     stream->caps =
         qtdemux_sub_caps (qtdemux, stream, fourcc, stsd_data, &codec);
     if (codec) {
-      list = gst_tag_list_new ();
+      list = gst_tag_list_new_empty ();
       gst_tag_list_add (list, GST_TAG_MERGE_REPLACE,
           GST_TAG_SUBTITLE_CODEC, codec, NULL);
       g_free (codec);
@@ -7429,7 +7445,7 @@ qtdemux_parse_trak (GstQTDemux * qtdemux, GNode * trak)
     const gchar *lang_code;
 
     if (!list)
-      list = gst_tag_list_new ();
+      list = gst_tag_list_new_empty ();
 
     /* convert ISO 639-2 code to ISO 639-1 */
     lang_code = gst_tag_get_language_code (stream->lang_id);
@@ -7495,7 +7511,6 @@ too_many_streams:
 static void
 gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
 {
-  GstFormat format = GST_FORMAT_BYTES;
   QtDemuxStream *stream = NULL;
   gint64 size, duration, sys_bitrate, sum_bitrate = 0;
   gint i;
@@ -7506,8 +7521,7 @@ gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
 
   GST_DEBUG_OBJECT (qtdemux, "Looking for streams with unknown bitrate");
 
-  if (!gst_pad_query_peer_duration (qtdemux->sinkpad, &format, &size) ||
-      format != GST_FORMAT_BYTES) {
+  if (!gst_pad_query_peer_duration (qtdemux->sinkpad, GST_FORMAT_BYTES, &size)) {
     GST_DEBUG_OBJECT (qtdemux,
         "Size in bytes of the stream not known - bailing");
     return;
@@ -7574,7 +7588,7 @@ gst_qtdemux_guess_bitrate (GstQTDemux * qtdemux)
       ", Stream bitrate = %u", sys_bitrate, bitrate);
 
   if (!stream->pending_tags)
-    stream->pending_tags = gst_tag_list_new ();
+    stream->pending_tags = gst_tag_list_new_empty ();
 
   gst_tag_list_add (stream->pending_tags, GST_TAG_MERGE_REPLACE,
       GST_TAG_BITRATE, bitrate, NULL);
@@ -7687,16 +7701,18 @@ qtdemux_is_brand_3gp (GstQTDemux * qtdemux, gboolean major)
     return ((qtdemux->major_brand & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
         GST_MAKE_FOURCC ('3', 'g', 0, 0));
   } else if (qtdemux->comp_brands != NULL) {
-    guint8 *data = GST_BUFFER_DATA (qtdemux->comp_brands);
-    guint size = GST_BUFFER_SIZE (qtdemux->comp_brands);
+    guint8 *data;
+    gsize size;
     gboolean res = FALSE;
 
+    data = gst_buffer_map (qtdemux->comp_brands, &size, NULL, GST_MAP_READ);
     while (size >= 4) {
       res = res || ((QT_FOURCC (data) & GST_MAKE_FOURCC (255, 255, 0, 0)) ==
           GST_MAKE_FOURCC ('3', 'g', 0, 0));
       data += 4;
       size -= 4;
     }
+    gst_buffer_unmap (qtdemux->comp_brands, data, size);
     return res;
   } else {
     return FALSE;
@@ -8350,6 +8366,41 @@ unknown_tag:
   }
 }
 
+static void
+qtdemux_tag_add_id32 (GstQTDemux * demux, const char *tag,
+    const char *tag_bis, GNode * node)
+{
+  guint8 *data;
+  GstBuffer *buf;
+  guint len;
+  GstTagList *taglist = NULL;
+
+  GST_LOG_OBJECT (demux, "parsing ID32");
+
+  data = node->data;
+  len = GST_READ_UINT32_BE (data);
+
+  /* need at least full box and language tag */
+  if (len < 12 + 2)
+    return;
+
+  buf = gst_buffer_new_allocate (NULL, len - 14, 0);
+  gst_buffer_fill (buf, 0, data + 14, len - 14);
+
+  taglist = gst_tag_list_from_id3v2_tag (buf);
+  if (taglist) {
+    GST_LOG_OBJECT (demux, "parsing ok");
+    gst_tag_list_insert (demux->tag_list, taglist, GST_TAG_MERGE_KEEP);
+  } else {
+    GST_LOG_OBJECT (demux, "parsing failed");
+  }
+
+  if (taglist)
+    gst_tag_list_free (taglist);
+
+  gst_buffer_unref (buf);
+}
+
 typedef void (*GstQTDemuxAddTagFunc) (GstQTDemux * demux,
     const char *tag, const char *tag_bis, GNode * node);
 
@@ -8419,7 +8470,9 @@ static const struct
      * http://atomicparsley.sourceforge.net/mpeg-4files.html and
      * bug #614471
      */
-  FOURCC_____, "", NULL, qtdemux_tag_add_revdns}
+  FOURCC_____, "", NULL, qtdemux_tag_add_revdns}, {
+    /* see http://www.mp4ra.org/specs.html for ID32 in meta box */
+  FOURCC_ID32, "", NULL, qtdemux_tag_add_id32}
 };
 
 static void
@@ -8437,7 +8490,7 @@ qtdemux_tag_add_blob (GNode * node, GstQTDemux * demux)
   data = node->data;
   len = QT_UINT32 (data);
   buf = gst_buffer_new_and_alloc (len);
-  memcpy (GST_BUFFER_DATA (buf), data, len);
+  _gst_buffer_copy_into_mem (buf, data, 0, len);
 
   /* heuristic to determine style of tag */
   if (QT_FOURCC (data + 4) == FOURCC_____ ||
@@ -8463,12 +8516,13 @@ qtdemux_tag_add_blob (GNode * node, GstQTDemux * demux)
   GST_DEBUG_OBJECT (demux, "media type %s", media_type);
 
   caps = gst_caps_new_simple (media_type, "style", G_TYPE_STRING, style, NULL);
-  gst_buffer_set_caps (buf, caps);
+  // TODO conver to metadata or ???
+//   gst_buffer_set_caps (buf, caps);
   gst_caps_unref (caps);
   g_free (media_type);
 
   GST_DEBUG_OBJECT (demux, "adding private tag; size %d, caps %" GST_PTR_FORMAT,
-      GST_BUFFER_SIZE (buf), caps);
+      len, caps);
 
   gst_tag_list_add (demux->tag_list, GST_TAG_MERGE_APPEND,
       GST_QT_DEMUX_PRIVATE_TAG, buf, NULL);
@@ -8498,7 +8552,7 @@ qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta)
 
   GST_DEBUG_OBJECT (qtdemux, "new tag list");
   if (!qtdemux->tag_list)
-    qtdemux->tag_list = gst_tag_list_new ();
+    qtdemux->tag_list = gst_tag_list_new_empty ();
 
   i = 0;
   while (i < G_N_ELEMENTS (add_funcs)) {
@@ -8530,10 +8584,8 @@ qtdemux_parse_udta (GstQTDemux * qtdemux, GNode * udta)
     GstBuffer *buf;
     GstTagList *taglist;
 
-    buf = gst_buffer_new ();
-    GST_BUFFER_DATA (buf) = ((guint8 *) xmp_->data) + 8;
-    GST_BUFFER_SIZE (buf) = QT_UINT32 ((guint8 *) xmp_->data) - 8;
-
+    buf = _gst_buffer_new_wrapped (((guint8 *) xmp_->data) + 8,
+        QT_UINT32 ((guint8 *) xmp_->data) - 8, NULL);
     taglist = gst_tag_list_from_xmp_buffer (buf);
     gst_buffer_unref (buf);
 
@@ -8718,7 +8770,7 @@ qtdemux_add_container_format (GstQTDemux * qtdemux, GstTagList * tags)
   const gchar *fmt;
 
   if (tags == NULL)
-    tags = gst_tag_list_new ();
+    tags = gst_tag_list_new_empty ();
 
   if (qtdemux->major_brand == FOURCC_mjp2)
     fmt = "Motion JPEG 2000";
@@ -8779,8 +8831,16 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
   /* Moving qt creation time (secs since 1904) to unix time */
   if (creation_time != 0) {
     if (creation_time > QTDEMUX_SECONDS_FROM_1904_TO_1970) {
+      GTimeVal now;
+
       creation_time -= QTDEMUX_SECONDS_FROM_1904_TO_1970;
-      datetime = gst_date_time_new_from_unix_epoch_local_time (creation_time);
+      /* some data cleansing sanity */
+      g_get_current_time (&now);
+      if (now.tv_sec + 24 * 3600 < creation_time) {
+        GST_DEBUG_OBJECT (qtdemux, "discarding bogus future creation time");
+      } else {
+        datetime = gst_date_time_new_from_unix_epoch_local_time (creation_time);
+      }
     } else {
       GST_WARNING_OBJECT (qtdemux, "Can't handle datetimes before 1970 yet, "
           "please file a bug at http://bugzilla.gnome.org");
@@ -8788,7 +8848,7 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
   }
   if (datetime) {
     if (!qtdemux->tag_list)
-      qtdemux->tag_list = gst_tag_list_new ();
+      qtdemux->tag_list = gst_tag_list_new_empty ();
 
     /* Use KEEP as explicit tags should have a higher priority than mvhd tag */
     gst_tag_list_add (qtdemux->tag_list, GST_TAG_MERGE_KEEP, GST_TAG_DATE_TIME,
@@ -8816,8 +8876,13 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
 
   /* set duration in the segment info */
   gst_qtdemux_get_duration (qtdemux, &duration);
-  if (duration)
-    gst_segment_set_duration (&qtdemux->segment, GST_FORMAT_TIME, duration);
+  if (duration) {
+    qtdemux->segment.duration = duration;
+    /* also do not exceed duration; stop is set that way post seek anyway,
+     * and segment activation falls back to duration,
+     * whereas loop only checks stop, so let's align this here as well */
+    qtdemux->segment.stop = duration;
+  }
 
   /* parse all traks */
   trak = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_trak);
@@ -8835,6 +8900,15 @@ qtdemux_parse_tree (GstQTDemux * qtdemux)
     GST_LOG_OBJECT (qtdemux, "No udta node found.");
   }
 
+  /* maybe also some tags in meta box */
+  udta = qtdemux_tree_get_child_by_type (qtdemux->moov_node, FOURCC_meta);
+  if (udta) {
+    GST_DEBUG_OBJECT (qtdemux, "Parsing meta box for tags.");
+    qtdemux_parse_udta (qtdemux, udta);
+  } else {
+    GST_LOG_OBJECT (qtdemux, "No meta node found.");
+  }
+
   qtdemux->tag_list = qtdemux_add_container_format (qtdemux, qtdemux->tag_list);
 
   return TRUE;
@@ -9008,11 +9082,11 @@ gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
           "systemstream", G_TYPE_BOOLEAN, FALSE, NULL);
       break;
     case 0x6C:                 /* MJPEG */
-      caps = gst_caps_new_simple ("image/jpeg", NULL);
+      caps = gst_caps_new_empty_simple ("image/jpeg");
       codec_name = "Motion-JPEG";
       break;
     case 0x6D:                 /* PNG */
-      caps = gst_caps_new_simple ("image/png", NULL);
+      caps = gst_caps_new_empty_simple ("image/png");
       codec_name = "PNG still images";
       break;
     case 0x6E:                 /* JPEG2000 */
@@ -9021,7 +9095,7 @@ gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
       break;
     case 0xA4:                 /* Dirac */
       codec_name = "Dirac";
-      caps = gst_caps_new_simple ("video/x-dirac", NULL);
+      caps = gst_caps_new_empty_simple ("video/x-dirac");
       break;
     case 0xA5:                 /* AC3 */
       codec_name = "AC-3 audio";
@@ -9031,7 +9105,7 @@ gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
     case 0xE1:                 /* QCELP */
       /* QCELP, the codec_data is a riff tag (little endian) with
        * more info (http://ftp.3gpp2.org/TSGC/Working/2003/2003-05-SanDiego/TSG-C-2003-05-San%20Diego/WG1/SWG12/C12-20030512-006%20=%20C12-20030217-015_Draft_Baseline%20Text%20of%20FFMS_R2.doc). */
-      caps = gst_caps_new_simple ("audio/qcelp", NULL);
+      caps = gst_caps_new_empty_simple ("audio/qcelp");
       codec_name = "QCELP";
       break;
     default:
@@ -9053,7 +9127,7 @@ gst_qtdemux_handle_esds (GstQTDemux * qtdemux, QtDemuxStream * stream,
     GstBuffer *buffer;
 
     buffer = gst_buffer_new_and_alloc (data_len);
-    memcpy (GST_BUFFER_DATA (buffer), data_ptr, data_len);
+    _gst_buffer_copy_into_mem (buffer, data_ptr, 0, data_len);
 
     GST_DEBUG_OBJECT (qtdemux, "setting codec_data from esds");
     GST_MEMDUMP_OBJECT (qtdemux, "codec_data from esds", data_ptr, data_len);
@@ -9083,22 +9157,22 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
   switch (fourcc) {
     case GST_MAKE_FOURCC ('p', 'n', 'g', ' '):
       _codec ("PNG still images");
-      caps = gst_caps_new_simple ("image/png", NULL);
+      caps = gst_caps_new_empty_simple ("image/png");
       break;
     case GST_MAKE_FOURCC ('j', 'p', 'e', 'g'):
       _codec ("JPEG still images");
-      caps = gst_caps_new_simple ("image/jpeg", NULL);
+      caps = gst_caps_new_empty_simple ("image/jpeg");
       break;
     case GST_MAKE_FOURCC ('m', 'j', 'p', 'a'):
     case GST_MAKE_FOURCC ('A', 'V', 'D', 'J'):
     case GST_MAKE_FOURCC ('M', 'J', 'P', 'G'):
     case GST_MAKE_FOURCC ('d', 'm', 'b', '1'):
       _codec ("Motion-JPEG");
-      caps = gst_caps_new_simple ("image/jpeg", NULL);
+      caps = gst_caps_new_empty_simple ("image/jpeg");
       break;
     case GST_MAKE_FOURCC ('m', 'j', 'p', 'b'):
       _codec ("Motion-JPEG format B");
-      caps = gst_caps_new_simple ("video/x-mjpeg-b", NULL);
+      caps = gst_caps_new_empty_simple ("video/x-mjpeg-b");
       break;
     case GST_MAKE_FOURCC ('m', 'j', 'p', '2'):
       _codec ("JPEG-2000");
@@ -9124,43 +9198,20 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
       _codec ("Raw RGB video");
       bps = QT_UINT16 (stsd_data + 98);
       /* set common stuff */
-      caps = gst_caps_new_simple ("video/x-raw-rgb",
-          "endianness", G_TYPE_INT, G_BYTE_ORDER, "depth", G_TYPE_INT, bps,
-          NULL);
+      caps = gst_caps_new_empty_simple ("video/x-raw");
 
       switch (bps) {
         case 15:
-          gst_caps_set_simple (caps,
-              "bpp", G_TYPE_INT, 16,
-              "endianness", G_TYPE_INT, G_BIG_ENDIAN,
-              "red_mask", G_TYPE_INT, 0x7c00,
-              "green_mask", G_TYPE_INT, 0x03e0,
-              "blue_mask", G_TYPE_INT, 0x001f, NULL);
+          gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB15", NULL);
           break;
         case 16:
-          gst_caps_set_simple (caps,
-              "bpp", G_TYPE_INT, 16,
-              "endianness", G_TYPE_INT, G_BIG_ENDIAN,
-              "red_mask", G_TYPE_INT, 0xf800,
-              "green_mask", G_TYPE_INT, 0x07e0,
-              "blue_mask", G_TYPE_INT, 0x001f, NULL);
+          gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB16", NULL);
           break;
         case 24:
-          gst_caps_set_simple (caps,
-              "bpp", G_TYPE_INT, 24,
-              "endianness", G_TYPE_INT, G_BIG_ENDIAN,
-              "red_mask", G_TYPE_INT, 0xff0000,
-              "green_mask", G_TYPE_INT, 0x00ff00,
-              "blue_mask", G_TYPE_INT, 0x0000ff, NULL);
+          gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB", NULL);
           break;
         case 32:
-          gst_caps_set_simple (caps,
-              "bpp", G_TYPE_INT, 32,
-              "endianness", G_TYPE_INT, G_BIG_ENDIAN,
-              "alpha_mask", G_TYPE_INT, 0xff000000,
-              "red_mask", G_TYPE_INT, 0x00ff0000,
-              "green_mask", G_TYPE_INT, 0x0000ff00,
-              "blue_mask", G_TYPE_INT, 0x000000ff, NULL);
+          gst_caps_set_simple (caps, "format", G_TYPE_STRING, "ARGB", NULL);
           break;
         default:
           /* unknown */
@@ -9170,39 +9221,30 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
     }
     case GST_MAKE_FOURCC ('y', 'v', '1', '2'):
       _codec ("Raw planar YUV 4:2:0");
-      caps = gst_caps_new_simple ("video/x-raw-yuv",
-          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'),
-          NULL);
+      caps = gst_caps_new_simple ("video/x-raw",
+          "format", G_TYPE_STRING, "I420", NULL);
       break;
     case GST_MAKE_FOURCC ('y', 'u', 'v', '2'):
     case GST_MAKE_FOURCC ('Y', 'u', 'v', '2'):
       _codec ("Raw packed YUV 4:2:2");
-      caps = gst_caps_new_simple ("video/x-raw-yuv",
-          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'),
-          NULL);
+      caps = gst_caps_new_simple ("video/x-raw",
+          "format", G_TYPE_STRING, "YUY2", NULL);
       break;
     case GST_MAKE_FOURCC ('2', 'v', 'u', 'y'):
     case GST_MAKE_FOURCC ('2', 'V', 'u', 'y'):
       _codec ("Raw packed YUV 4:2:2");
-      caps = gst_caps_new_simple ("video/x-raw-yuv",
-          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'),
-          NULL);
+      caps = gst_caps_new_simple ("video/x-raw",
+          "format", G_TYPE_STRING, "UYVY", NULL);
       break;
     case GST_MAKE_FOURCC ('v', '2', '1', '0'):
       _codec ("Raw packed YUV 10-bit 4:2:2");
-      caps = gst_caps_new_simple ("video/x-raw-yuv",
-          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('v', '2', '1', '0'),
-          NULL);
+      caps = gst_caps_new_simple ("video/x-raw",
+          "format", G_TYPE_STRING, "v210", NULL);
       break;
     case GST_MAKE_FOURCC ('r', '2', '1', '0'):
       _codec ("Raw packed RGB 10-bit 4:4:4");
-      caps = gst_caps_new_simple ("video/x-raw-rgb",
-          "endianness", G_TYPE_INT, G_BIG_ENDIAN, "depth", G_TYPE_INT, 30,
-          "bpp", G_TYPE_INT, 32,
-          "endianness", G_TYPE_INT, G_BIG_ENDIAN,
-          "red_mask", G_TYPE_INT, 0x3ff00000,
-          "green_mask", G_TYPE_INT, 0x000ffc00,
-          "blue_mask", G_TYPE_INT, 0x000003ff, NULL);
+      caps = gst_caps_new_simple ("video/x-raw",
+          "format", G_TYPE_STRING, "r210", NULL);
       break;
     case GST_MAKE_FOURCC ('m', 'p', 'e', 'g'):
     case GST_MAKE_FOURCC ('m', 'p', 'g', '1'):
@@ -9230,7 +9272,7 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
       break;
     case GST_MAKE_FOURCC ('g', 'i', 'f', ' '):
       _codec ("GIF still images");
-      caps = gst_caps_new_simple ("image/gif", NULL);
+      caps = gst_caps_new_empty_simple ("image/gif");
       break;
     case GST_MAKE_FOURCC ('h', '2', '6', '3'):
     case GST_MAKE_FOURCC ('H', '2', '6', '3'):
@@ -9238,7 +9280,7 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
     case GST_MAKE_FOURCC ('U', '2', '6', '3'):
       _codec ("H.263");
       /* ffmpeg uses the height/width props, don't know why */
-      caps = gst_caps_new_simple ("video/x-h263", NULL);
+      caps = gst_caps_new_empty_simple ("video/x-h263");
       break;
     case GST_MAKE_FOURCC ('m', 'p', '4', 'v'):
     case GST_MAKE_FOURCC ('M', 'P', '4', 'V'):
@@ -9255,7 +9297,7 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
     case GST_MAKE_FOURCC ('3', 'I', 'V', '1'):
     case GST_MAKE_FOURCC ('3', 'I', 'V', '2'):
       _codec ("3ivX video");
-      caps = gst_caps_new_simple ("video/x-3ivx", NULL);
+      caps = gst_caps_new_empty_simple ("video/x-3ivx");
       break;
     case GST_MAKE_FOURCC ('D', 'I', 'V', '3'):
       _codec ("DivX 3");
@@ -9276,7 +9318,7 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
     case GST_MAKE_FOURCC ('X', 'V', 'I', 'D'):
     case GST_MAKE_FOURCC ('x', 'v', 'i', 'd'):
       _codec ("XVID MPEG-4");
-      caps = gst_caps_new_simple ("video/x-xvid", NULL);
+      caps = gst_caps_new_empty_simple ("video/x-xvid");
       break;
 
     case GST_MAKE_FOURCC ('F', 'M', 'P', '4'):
@@ -9289,15 +9331,15 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
 
     case GST_MAKE_FOURCC ('c', 'v', 'i', 'd'):
       _codec ("Cinepak");
-      caps = gst_caps_new_simple ("video/x-cinepak", NULL);
+      caps = gst_caps_new_empty_simple ("video/x-cinepak");
       break;
     case GST_MAKE_FOURCC ('q', 'd', 'r', 'w'):
       _codec ("Apple QuickDraw");
-      caps = gst_caps_new_simple ("video/x-qdrw", NULL);
+      caps = gst_caps_new_empty_simple ("video/x-qdrw");
       break;
     case GST_MAKE_FOURCC ('r', 'p', 'z', 'a'):
       _codec ("Apple video");
-      caps = gst_caps_new_simple ("video/x-apple-video", NULL);
+      caps = gst_caps_new_empty_simple ("video/x-apple-video");
       break;
     case GST_MAKE_FOURCC ('a', 'v', 'c', '1'):
       _codec ("H.264 / AVC");
@@ -9348,26 +9390,26 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
       break;
     case GST_MAKE_FOURCC ('s', 'm', 'c', ' '):
       _codec ("Apple Graphics (SMC)");
-      caps = gst_caps_new_simple ("video/x-smc", NULL);
+      caps = gst_caps_new_empty_simple ("video/x-smc");
       break;
     case GST_MAKE_FOURCC ('V', 'P', '3', '1'):
       _codec ("VP3");
-      caps = gst_caps_new_simple ("video/x-vp3", NULL);
+      caps = gst_caps_new_empty_simple ("video/x-vp3");
       break;
     case GST_MAKE_FOURCC ('X', 'i', 'T', 'h'):
       _codec ("Theora");
-      caps = gst_caps_new_simple ("video/x-theora", NULL);
+      caps = gst_caps_new_empty_simple ("video/x-theora");
       /* theora uses one byte of padding in the data stream because it does not
        * allow 0 sized packets while theora does */
       stream->padding = 1;
       break;
     case GST_MAKE_FOURCC ('d', 'r', 'a', 'c'):
       _codec ("Dirac");
-      caps = gst_caps_new_simple ("video/x-dirac", NULL);
+      caps = gst_caps_new_empty_simple ("video/x-dirac");
       break;
     case GST_MAKE_FOURCC ('t', 'i', 'f', 'f'):
       _codec ("TIFF still images");
-      caps = gst_caps_new_simple ("image/tiff", NULL);
+      caps = gst_caps_new_empty_simple ("image/tiff");
       break;
     case GST_MAKE_FOURCC ('i', 'c', 'o', 'd'):
       _codec ("Apple Intermediate Codec");
@@ -9384,9 +9426,7 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
     case FOURCC_ovc1:
       _codec ("VC-1");
       caps = gst_caps_new_simple ("video/x-wmv",
-          "wmvversion", G_TYPE_INT, 3,
-          "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'V', 'C', '1'),
-          NULL);
+          "wmvversion", G_TYPE_INT, 3, "format", G_TYPE_STRING, "WVC1", NULL);
       break;
     case GST_MAKE_FOURCC ('k', 'p', 'c', 'd'):
     default:
@@ -9395,7 +9435,7 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
 
       s = g_strdup_printf ("video/x-gst-fourcc-%" GST_FOURCC_FORMAT,
           GST_FOURCC_ARGS (fourcc));
-      caps = gst_caps_new_simple (s, NULL);
+      caps = gst_caps_new_empty_simple (s);
       break;
     }
   }
@@ -9403,7 +9443,7 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
   /* enable clipping for raw video streams */
   s = gst_caps_get_structure (caps, 0);
   name = gst_structure_get_name (s);
-  if (g_str_has_prefix (name, "video/x-raw-")) {
+  if (g_str_has_prefix (name, "video/x-raw")) {
     stream->need_clip = TRUE;
   }
   return caps;
@@ -9424,8 +9464,8 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
     case GST_MAKE_FOURCC ('N', 'O', 'N', 'E'):
     case GST_MAKE_FOURCC ('r', 'a', 'w', ' '):
       _codec ("Raw 8-bit PCM audio");
-      caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 8,
-          "depth", G_TYPE_INT, 8, "signed", G_TYPE_BOOLEAN, FALSE, NULL);
+      caps = gst_caps_new_simple ("audio/x-raw",
+          "format", G_TYPE_STRING, "U8", NULL);
       break;
     case GST_MAKE_FOURCC ('t', 'w', 'o', 's'):
       endian = G_BIG_ENDIAN;
@@ -9434,53 +9474,51 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
     {
       gchar *str;
       gint depth;
+      GstAudioFormat format;
 
       if (!endian)
         endian = G_LITTLE_ENDIAN;
 
       depth = stream->bytes_per_packet * 8;
+      format = gst_audio_format_build_integer (TRUE, endian, depth, depth);
+
       str = g_strdup_printf ("Raw %d-bit PCM audio", depth);
       _codec (str);
       g_free (str);
-      caps = gst_caps_new_simple ("audio/x-raw-int",
-          "width", G_TYPE_INT, depth, "depth", G_TYPE_INT, depth,
-          "endianness", G_TYPE_INT, endian,
-          "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+
+      caps = gst_caps_new_simple ("audio/x-raw",
+          "format", G_TYPE_STRING, gst_audio_format_to_string (format), NULL);
       break;
     }
     case GST_MAKE_FOURCC ('f', 'l', '6', '4'):
       _codec ("Raw 64-bit floating-point audio");
-      caps = gst_caps_new_simple ("audio/x-raw-float", "width", G_TYPE_INT, 64,
-          "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL);
+      caps = gst_caps_new_simple ("audio/x-raw",
+          "format", G_TYPE_STRING, "F64BE", NULL);
       break;
     case GST_MAKE_FOURCC ('f', 'l', '3', '2'):
       _codec ("Raw 32-bit floating-point audio");
-      caps = gst_caps_new_simple ("audio/x-raw-float", "width", G_TYPE_INT, 32,
-          "endianness", G_TYPE_INT, G_BIG_ENDIAN, NULL);
+      caps = gst_caps_new_simple ("audio/x-raw",
+          "format", G_TYPE_STRING, "F32BE", NULL);
       break;
     case FOURCC_in24:
       _codec ("Raw 24-bit PCM audio");
       /* we assume BIG ENDIAN, an enda box will tell us to change this to little
        * endian later */
-      caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 24,
-          "depth", G_TYPE_INT, 24,
-          "endianness", G_TYPE_INT, G_BIG_ENDIAN,
-          "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+      caps = gst_caps_new_simple ("audio/x-raw",
+          "format", G_TYPE_STRING, "S24BE", NULL);
       break;
     case GST_MAKE_FOURCC ('i', 'n', '3', '2'):
       _codec ("Raw 32-bit PCM audio");
-      caps = gst_caps_new_simple ("audio/x-raw-int", "width", G_TYPE_INT, 32,
-          "depth", G_TYPE_INT, 32,
-          "endianness", G_TYPE_INT, G_BIG_ENDIAN,
-          "signed", G_TYPE_BOOLEAN, TRUE, NULL);
+      caps = gst_caps_new_simple ("audio/x-raw",
+          "format", G_TYPE_STRING, "S32BE", NULL);
       break;
     case GST_MAKE_FOURCC ('u', 'l', 'a', 'w'):
       _codec ("Mu-law audio");
-      caps = gst_caps_new_simple ("audio/x-mulaw", NULL);
+      caps = gst_caps_new_empty_simple ("audio/x-mulaw");
       break;
     case GST_MAKE_FOURCC ('a', 'l', 'a', 'w'):
       _codec ("A-law audio");
-      caps = gst_caps_new_simple ("audio/x-alaw", NULL);
+      caps = gst_caps_new_empty_simple ("audio/x-alaw");
       break;
     case 0x0200736d:
     case 0x6d730002:
@@ -9536,11 +9574,11 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
       break;
     case GST_MAKE_FOURCC ('O', 'g', 'g', 'V'):
       /* ogg/vorbis */
-      caps = gst_caps_new_simple ("application/ogg", NULL);
+      caps = gst_caps_new_empty_simple ("application/ogg");
       break;
     case GST_MAKE_FOURCC ('d', 'v', 'c', 'a'):
       _codec ("DV audio");
-      caps = gst_caps_new_simple ("audio/x-dv", NULL);
+      caps = gst_caps_new_empty_simple ("audio/x-dv");
       break;
     case GST_MAKE_FOURCC ('m', 'p', '4', 'a'):
       _codec ("MPEG-4 AAC audio");
@@ -9550,7 +9588,7 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
       break;
     case GST_MAKE_FOURCC ('Q', 'D', 'M', 'C'):
       _codec ("QDesign Music");
-      caps = gst_caps_new_simple ("audio/x-qdm", NULL);
+      caps = gst_caps_new_empty_simple ("audio/x-qdm");
       break;
     case GST_MAKE_FOURCC ('Q', 'D', 'M', '2'):
       _codec ("QDesign Music v.2");
@@ -9561,20 +9599,20 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
             "bitrate", G_TYPE_INT, QT_UINT32 (data + 40),
             "blocksize", G_TYPE_INT, QT_UINT32 (data + 44), NULL);
       } else {
-        caps = gst_caps_new_simple ("audio/x-qdm2", NULL);
+        caps = gst_caps_new_empty_simple ("audio/x-qdm2");
       }
       break;
     case GST_MAKE_FOURCC ('a', 'g', 's', 'm'):
       _codec ("GSM audio");
-      caps = gst_caps_new_simple ("audio/x-gsm", NULL);
+      caps = gst_caps_new_empty_simple ("audio/x-gsm");
       break;
     case GST_MAKE_FOURCC ('s', 'a', 'm', 'r'):
       _codec ("AMR audio");
-      caps = gst_caps_new_simple ("audio/AMR", NULL);
+      caps = gst_caps_new_empty_simple ("audio/AMR");
       break;
     case GST_MAKE_FOURCC ('s', 'a', 'w', 'b'):
       _codec ("AMR-WB audio");
-      caps = gst_caps_new_simple ("audio/AMR-WB", NULL);
+      caps = gst_caps_new_empty_simple ("audio/AMR-WB");
       break;
     case GST_MAKE_FOURCC ('i', 'm', 'a', '4'):
       _codec ("Quicktime IMA ADPCM");
@@ -9583,7 +9621,7 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
       break;
     case GST_MAKE_FOURCC ('a', 'l', 'a', 'c'):
       _codec ("Apple lossless audio");
-      caps = gst_caps_new_simple ("audio/x-alac", NULL);
+      caps = gst_caps_new_empty_simple ("audio/x-alac");
       break;
     case GST_MAKE_FOURCC ('Q', 'c', 'l', 'p'):
       _codec ("QualComm PureVoice");
@@ -9591,7 +9629,7 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
       break;
     case FOURCC_owma:
       _codec ("WMA");
-      caps = gst_caps_new_simple ("audio/x-wma", NULL);
+      caps = gst_caps_new_empty_simple ("audio/x-wma");
       break;
     case GST_MAKE_FOURCC ('q', 't', 'v', 'r'):
       /* ? */
@@ -9601,7 +9639,7 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
 
       s = g_strdup_printf ("audio/x-gst-fourcc-%" GST_FOURCC_FORMAT,
           GST_FOURCC_ARGS (fourcc));
-      caps = gst_caps_new_simple (s, NULL);
+      caps = gst_caps_new_empty_simple (s);
       break;
     }
   }
@@ -9609,7 +9647,7 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
   /* enable clipping for raw audio streams */
   s = gst_caps_get_structure (caps, 0);
   name = gst_structure_get_name (s);
-  if (g_str_has_prefix (name, "audio/x-raw-")) {
+  if (g_str_has_prefix (name, "audio/x-raw")) {
     stream->need_clip = TRUE;
   }
   return caps;
@@ -9626,7 +9664,7 @@ qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
   switch (fourcc) {
     case GST_MAKE_FOURCC ('m', 'p', '4', 's'):
       _codec ("DVD subtitle");
-      caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL);
+      caps = gst_caps_new_empty_simple ("video/x-dvd-subpicture");
       break;
     case GST_MAKE_FOURCC ('t', 'e', 'x', 't'):
       _codec ("Quicktime timed text");
@@ -9634,7 +9672,7 @@ qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
     case GST_MAKE_FOURCC ('t', 'x', '3', 'g'):
       _codec ("3GPP timed text");
     text:
-      caps = gst_caps_new_simple ("text/plain", NULL);
+      caps = gst_caps_new_empty_simple ("text/plain");
       /* actual text piece needs to be extracted */
       stream->need_process = TRUE;
       break;
@@ -9644,7 +9682,7 @@ qtdemux_sub_caps (GstQTDemux * qtdemux, QtDemuxStream * stream,
 
       s = g_strdup_printf ("text/x-gst-fourcc-%" GST_FOURCC_FORMAT,
           GST_FOURCC_ARGS (fourcc));
-      caps = gst_caps_new_simple (s, NULL);
+      caps = gst_caps_new_empty_simple (s);
       break;
     }
   }