dv: port to 0.11
authorMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Mon, 6 Feb 2012 21:13:53 +0000 (22:13 +0100)
committerMark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
Mon, 6 Feb 2012 21:15:45 +0000 (22:15 +0100)
configure.ac
ext/dv/Makefile.am
ext/dv/gstdvdec.c
ext/dv/gstdvdec.h
ext/dv/gstdvdemux.c
ext/dv/gstdvdemux.h

index 51b5790..f7a2075 100644 (file)
@@ -314,7 +314,7 @@ dnl Make sure you have a space before and after all plugins
 GST_PLUGINS_NONPORTED="deinterlace interleave flx goom2k1 \
  imagefreeze interleave monoscope smpte \
  videobox \
- cairo cairo_gobject dv1394 gdk_pixbuf libdv \
+ cairo cairo_gobject dv1394 gdk_pixbuf \
  oss oss4 shout2 \
  wavpack \
  osx_video osx_audio "
index e63154d..4091a5e 100644 (file)
@@ -3,8 +3,8 @@ plugin_LTLIBRARIES = libgstdv.la
 libgstdv_la_SOURCES = gstdv.c gstdvdec.c gstdvdemux.c gstsmptetimecode.c
 libgstdv_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(LIBDV_CFLAGS)
 libgstdv_la_LIBADD = \
-       $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) \
-        $(GST_BASE_LIBS) $(GST_LIBS) $(LIBDV_LIBS)
+       $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) -lgstvideo-$(GST_MAJORMINOR) \
+       $(GST_BASE_LIBS) $(GST_LIBS) $(LIBDV_LIBS)
 libgstdv_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
 libgstdv_la_LIBTOOLFLAGS = --tag=disable-static
 
index e7fd946..84912e5 100644 (file)
@@ -44,6 +44,7 @@
 #include <string.h>
 #include <math.h>
 #include <gst/video/video.h>
+#include <gst/video/gstvideopool.h>
 
 #include "gstdvdec.h"
 
@@ -101,27 +102,10 @@ static GstStaticPadTemplate sink_temp = GST_STATIC_PAD_TEMPLATE ("sink",
 static GstStaticPadTemplate src_temp = GST_STATIC_PAD_TEMPLATE ("src",
     GST_PAD_SRC,
     GST_PAD_ALWAYS,
-    GST_STATIC_CAPS ("video/x-raw-yuv, "
-        "format = (fourcc) YUY2, "
-        "width = (int) 720, "
-        "framerate = (fraction) [ 1/1, 60/1 ];"
-        "video/x-raw-rgb, "
-        "bpp = (int) 32, "
-        "depth = (int) 24, "
-        "endianness = (int) " G_STRINGIFY (G_BIG_ENDIAN) ", "
-        "red_mask =   (int) 0x0000ff00, "
-        "green_mask = (int) 0x00ff0000, "
-        "blue_mask =  (int) 0xff000000, "
-        "width = (int) 720, "
-        "framerate = (fraction) [ 1/1, 60/1 ];"
-        "video/x-raw-rgb, "
-        "bpp = (int) 24, "
-        "depth = (int) 24, "
-        "endianness = (int) " G_STRINGIFY (G_BIG_ENDIAN) ", "
-        "red_mask =   (int) 0x00ff0000, "
-        "green_mask = (int) 0x0000ff00, "
-        "blue_mask =  (int) 0x000000ff, "
-        "width = (int) 720, " "framerate = (fraction) [ 1/1, 60/1 ]")
+    GST_STATIC_CAPS ("video/x-raw, "
+        "format = (string) { YUY2, BGRx, RGB }, "
+        "framerate = (fraction) [ 1/1, 60/1 ], "
+        "width = (int) 720, " "height = (int) { 576, 480 }")
     );
 
 #define GST_TYPE_DVDEC_QUALITY (gst_dvdec_quality_get_type())
@@ -146,12 +130,13 @@ gst_dvdec_quality_get_type (void)
   return qtype;
 }
 
-GST_BOILERPLATE (GstDVDec, gst_dvdec, GstElement, GST_TYPE_ELEMENT);
+#define gst_dvdec_parent_class parent_class
+G_DEFINE_TYPE (GstDVDec, gst_dvdec, GST_TYPE_ELEMENT);
 
-static void gst_dvdec_finalize (GObject * object);
-static gboolean gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps);
-static GstFlowReturn gst_dvdec_chain (GstPad * pad, GstBuffer * buffer);
-static gboolean gst_dvdec_sink_event (GstPad * pad, GstEvent * event);
+static GstFlowReturn gst_dvdec_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer);
+static gboolean gst_dvdec_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
 
 static GstStateChangeReturn gst_dvdec_change_state (GstElement * element,
     GstStateChange transition);
@@ -162,24 +147,6 @@ static void gst_dvdec_get_property (GObject * object, guint prop_id,
     GValue * value, GParamSpec * pspec);
 
 static void
-gst_dvdec_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sink_temp));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&src_temp));
-
-  gst_element_class_set_details_simple (element_class, "DV video decoder",
-      "Codec/Decoder/Video",
-      "Uses libdv to decode DV video (smpte314) (libdv.sourceforge.net)",
-      "Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
-
-  GST_DEBUG_CATEGORY_INIT (dvdec_debug, "dvdec", 0, "DV decoding element");
-}
-
-static void
 gst_dvdec_class_init (GstDVDecClass * klass)
 {
   GObjectClass *gobject_class;
@@ -188,7 +155,6 @@ gst_dvdec_class_init (GstDVDecClass * klass)
   gobject_class = (GObjectClass *) klass;
   gstelement_class = (GstElementClass *) klass;
 
-  gobject_class->finalize = gst_dvdec_finalize;
   gobject_class->set_property = gst_dvdec_set_property;
   gobject_class->get_property = gst_dvdec_get_property;
 
@@ -207,15 +173,25 @@ gst_dvdec_class_init (GstDVDecClass * klass)
           1, G_MAXINT, DV_DEFAULT_DECODE_NTH,
           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
-  gstelement_class->change_state = gst_dvdec_change_state;
+  gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dvdec_change_state);
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sink_temp));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&src_temp));
+
+  gst_element_class_set_details_simple (gstelement_class, "DV video decoder",
+      "Codec/Decoder/Video",
+      "Uses libdv to decode DV video (smpte314) (libdv.sourceforge.net)",
+      "Erik Walthinsen <omega@cse.ogi.edu>," "Wim Taymans <wim@fluendo.com>");
+
+  GST_DEBUG_CATEGORY_INIT (dvdec_debug, "dvdec", 0, "DV decoding element");
 }
 
 static void
-gst_dvdec_init (GstDVDec * dvdec, GstDVDecClass * g_class)
+gst_dvdec_init (GstDVDec * dvdec)
 {
   dvdec->sinkpad = gst_pad_new_from_static_template (&sink_temp, "sink");
-  gst_pad_set_setcaps_function (dvdec->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_dvdec_sink_setcaps));
   gst_pad_set_chain_function (dvdec->sinkpad, gst_dvdec_chain);
   gst_pad_set_event_function (dvdec->sinkpad, gst_dvdec_sink_event);
   gst_element_add_pad (GST_ELEMENT (dvdec), dvdec->sinkpad);
@@ -232,28 +208,14 @@ gst_dvdec_init (GstDVDec * dvdec, GstDVDecClass * g_class)
   dvdec->clamp_luma = FALSE;
   dvdec->clamp_chroma = FALSE;
   dvdec->quality = DV_DEFAULT_QUALITY;
-  dvdec->segment = gst_segment_new ();
-}
-
-static void
-gst_dvdec_finalize (GObject * object)
-{
-  GstDVDec *dvdec = GST_DVDEC (object);
-
-  gst_segment_free (dvdec->segment);
-
-  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 static gboolean
-gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps)
+gst_dvdec_sink_setcaps (GstDVDec * dvdec, GstCaps * caps)
 {
-  GstDVDec *dvdec;
   GstStructure *s;
   const GValue *par = NULL, *rate = NULL;
 
-  dvdec = GST_DVDEC (gst_pad_get_parent (pad));
-
   /* first parse the caps */
   s = gst_caps_get_structure (caps, 0);
 
@@ -276,19 +238,64 @@ gst_dvdec_sink_setcaps (GstPad * pad, GstCaps * caps)
   dvdec->sink_negotiated = TRUE;
   dvdec->src_negotiated = FALSE;
 
-  gst_object_unref (dvdec);
-
   return TRUE;
 
   /* ERRORS */
 no_framerate:
   {
     GST_DEBUG_OBJECT (dvdec, "no framerate specified in caps");
-    gst_object_unref (dvdec);
     return FALSE;
   }
 }
 
+static void
+gst_dvdec_negotiate_pool (GstDVDec * dec, GstCaps * caps, GstVideoInfo * info)
+{
+  GstQuery *query;
+  GstBufferPool *pool = NULL;
+  guint size, min, max, prefix, alignment;
+  GstStructure *config;
+
+  /* find a pool for the negotiated caps now */
+  query = gst_query_new_allocation (caps, TRUE);
+
+  if (gst_pad_peer_query (dec->srcpad, query)) {
+    GST_DEBUG_OBJECT (dec, "got downstream ALLOCATION hints");
+    /* we got configuration from our peer, parse them */
+    gst_query_parse_allocation_params (query, &size, &min, &max, &prefix,
+        &alignment, &pool);
+    size = MAX (size, info->size);
+  } else {
+    GST_DEBUG_OBJECT (dec, "didn't get downstream ALLOCATION hints");
+    size = info->size;
+    min = max = 0;
+    prefix = 0;
+    alignment = 0;
+  }
+
+  if (pool == NULL) {
+    /* we did not get a pool, make one ourselves then */
+    pool = gst_buffer_pool_new ();
+  }
+
+  if (dec->pool)
+    gst_object_unref (dec->pool);
+  dec->pool = pool;
+
+  config = gst_buffer_pool_get_config (pool);
+  gst_buffer_pool_config_set (config, caps, size, min, max, prefix, alignment);
+  /* just set the option, if the pool can support it we will transparently use
+   * it through the video info API. We could also see if the pool support this
+   * option and only activate it then. */
+  gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
+
+  gst_buffer_pool_set_config (pool, config);
+  /* and activate */
+  gst_buffer_pool_set_active (pool, TRUE);
+
+  gst_query_unref (query);
+}
+
 static gboolean
 gst_dvdec_src_negotiate (GstDVDec * dvdec)
 {
@@ -320,16 +327,24 @@ gst_dvdec_src_negotiate (GstDVDec * dvdec)
   /* ignoring rgb, bgr0 for now */
   dvdec->bpp = 2;
 
-  othercaps = gst_caps_new_simple ("video/x-raw-yuv",
-      "format", GST_TYPE_FOURCC, GST_STR_FOURCC ("YUY2"),
-      "width", G_TYPE_INT, 720,
-      "height", G_TYPE_INT, dvdec->height,
-      "framerate", GST_TYPE_FRACTION, dvdec->framerate_numerator,
-      dvdec->framerate_denominator,
-      "pixel-aspect-ratio", GST_TYPE_FRACTION, dvdec->par_x,
-      dvdec->par_y, "interlaced", G_TYPE_BOOLEAN, dvdec->interlaced, NULL);
+  gst_video_info_set_format (&dvdec->vinfo, GST_VIDEO_FORMAT_YUY2,
+      720, dvdec->height);
+  dvdec->vinfo.fps_n = dvdec->framerate_numerator;
+  dvdec->vinfo.fps_d = dvdec->framerate_denominator;
+  dvdec->vinfo.par_n = dvdec->par_x;
+  dvdec->vinfo.par_d = dvdec->par_y;
+  if (dvdec->interlaced) {
+    dvdec->vinfo.interlace_mode = GST_VIDEO_INTERLACE_MODE_INTERLEAVED;
+    dvdec->vinfo.flags |= GST_VIDEO_FLAG_INTERLACED;
+  } else {
+    dvdec->vinfo.interlace_mode = GST_VIDEO_INTERLACE_MODE_PROGRESSIVE;
+    dvdec->vinfo.flags &= GST_VIDEO_FLAG_INTERLACED;
+  }
 
+  othercaps = gst_video_info_to_caps (&dvdec->vinfo);
   gst_pad_set_caps (dvdec->srcpad, othercaps);
+
+  gst_dvdec_negotiate_pool (dvdec, othercaps, &dvdec->vinfo);
   gst_caps_unref (othercaps);
 
   dvdec->src_negotiated = TRUE;
@@ -338,69 +353,77 @@ gst_dvdec_src_negotiate (GstDVDec * dvdec)
 }
 
 static gboolean
-gst_dvdec_sink_event (GstPad * pad, GstEvent * event)
+gst_dvdec_sink_event (GstPad * pad, GstObject * parent, GstEvent * event)
 {
   GstDVDec *dvdec;
   gboolean res = TRUE;
 
-  dvdec = GST_DVDEC (gst_pad_get_parent (pad));
+  dvdec = GST_DVDEC (parent);
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_FLUSH_STOP:
-      gst_segment_init (dvdec->segment, GST_FORMAT_UNDEFINED);
+      gst_segment_init (&dvdec->segment, GST_FORMAT_UNDEFINED);
       break;
-    case GST_EVENT_NEWSEGMENT:{
-      gboolean update;
-      gdouble rate, applied_rate;
-      GstFormat format;
-      gint64 start, stop, position;
-
-      gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate,
-          &format, &start, &stop, &position);
-
-      GST_DEBUG_OBJECT (dvdec, "Got NEWSEGMENT [%" GST_TIME_FORMAT
-          " - %" GST_TIME_FORMAT " / %" GST_TIME_FORMAT "]",
-          GST_TIME_ARGS (start), GST_TIME_ARGS (stop),
-          GST_TIME_ARGS (position));
-
-      gst_segment_set_newsegment_full (dvdec->segment, update, rate,
-          applied_rate, format, start, stop, position);
+    case GST_EVENT_SEGMENT:{
+      const GstSegment *segment;
+
+      gst_event_parse_segment (event, &segment);
+
+      GST_DEBUG_OBJECT (dvdec, "Got NEWSEGMENT %" GST_SEGMENT_FORMAT, &segment);
+
+      gst_segment_copy_into (segment, &dvdec->segment);
+      break;
+    }
+    case GST_EVENT_CAPS:
+    {
+      GstCaps *caps;
+
+      gst_event_parse_caps (event, &caps);
+      gst_dvdec_sink_setcaps (dvdec, caps);
+      gst_event_unref (event);
+      event = NULL;
+      res = TRUE;
       break;
     }
+
     default:
       break;
   }
 
-  res = gst_pad_push_event (dvdec->srcpad, event);
+  if (event)
+    res = gst_pad_push_event (dvdec->srcpad, event);
 
   return res;
 }
 
 static GstFlowReturn
-gst_dvdec_chain (GstPad * pad, GstBuffer * buf)
+gst_dvdec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
 {
   GstDVDec *dvdec;
   guint8 *inframe;
-  guint8 *outframe;
   guint8 *outframe_ptrs[3];
   gint outframe_pitches[3];
+  GstMapInfo map;
+  GstVideoFrame frame;
   GstBuffer *outbuf;
   GstFlowReturn ret = GST_FLOW_OK;
   guint length;
-  gint64 cstart, cstop;
+  guint64 cstart, cstop;
   gboolean PAL, wide;
 
-  dvdec = GST_DVDEC (gst_pad_get_parent (pad));
-  inframe = GST_BUFFER_DATA (buf);
+  dvdec = GST_DVDEC (parent);
+
+  gst_buffer_map (buf, &map, GST_MAP_READ);
+  inframe = map.data;
 
   /* buffer should be at least the size of one NTSC frame, this should
    * be enough to decode the header. */
-  if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < NTSC_BUFFER))
+  if (G_UNLIKELY (map.size < NTSC_BUFFER))
     goto wrong_size;
 
   /* preliminary dropping. unref and return if outside of configured segment */
-  if ((dvdec->segment->format == GST_FORMAT_TIME) &&
-      (!(gst_segment_clip (dvdec->segment, GST_FORMAT_TIME,
+  if ((dvdec->segment.format == GST_FORMAT_TIME) &&
+      (!(gst_segment_clip (&dvdec->segment, GST_FORMAT_TIME,
                   GST_BUFFER_TIMESTAMP (buf),
                   GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf),
                   &cstart, &cstop))))
@@ -416,7 +439,7 @@ gst_dvdec_chain (GstPad * pad, GstBuffer * buf)
   /* check the buffer is of right size after we know if we are
    * dealing with PAL or NTSC */
   length = (PAL ? PAL_BUFFER : NTSC_BUFFER);
-  if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < length))
+  if (G_UNLIKELY (map.size < length))
     goto wrong_size;
 
   dv_parse_packs (dvdec->decoder, inframe);
@@ -441,32 +464,39 @@ gst_dvdec_chain (GstPad * pad, GstBuffer * buf)
       goto not_negotiated;
   }
 
-  ret =
-      gst_pad_alloc_buffer_and_set_caps (dvdec->srcpad, 0,
-      (720 * dvdec->height) * dvdec->bpp,
-      GST_PAD_CAPS (dvdec->srcpad), &outbuf);
+  if (gst_pad_check_reconfigure (dvdec->srcpad)) {
+    GstCaps *caps;
+
+    caps = gst_pad_get_current_caps (dvdec->srcpad);
+    gst_dvdec_negotiate_pool (dvdec, caps, &dvdec->vinfo);
+    gst_caps_unref (caps);
+  }
+
+  ret = gst_buffer_pool_acquire_buffer (dvdec->pool, &outbuf, NULL);
   if (G_UNLIKELY (ret != GST_FLOW_OK))
     goto no_buffer;
 
-  outframe = GST_BUFFER_DATA (outbuf);
+  gst_video_frame_map (&frame, &dvdec->vinfo, outbuf, GST_MAP_WRITE);
 
-  outframe_ptrs[0] = outframe;
-  outframe_pitches[0] = 720 * dvdec->bpp;
+  outframe_ptrs[0] = GST_VIDEO_FRAME_COMP_DATA (&frame, 0);
+  outframe_pitches[0] = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 0);
 
   /* the rest only matters for YUY2 */
   if (dvdec->bpp < 3) {
-    outframe_ptrs[1] = outframe_ptrs[0] + 720 * dvdec->height;
-    outframe_ptrs[2] = outframe_ptrs[1] + 360 * dvdec->height;
+    outframe_ptrs[1] = GST_VIDEO_FRAME_COMP_DATA (&frame, 1);
+    outframe_ptrs[2] = GST_VIDEO_FRAME_COMP_DATA (&frame, 2);
 
-    outframe_pitches[1] = dvdec->height / 2;
-    outframe_pitches[2] = outframe_pitches[1];
+    outframe_pitches[1] = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 1);
+    outframe_pitches[2] = GST_VIDEO_FRAME_COMP_STRIDE (&frame, 2);
   }
 
   GST_DEBUG_OBJECT (dvdec, "decoding and pushing buffer");
   dv_decode_full_frame (dvdec->decoder, inframe,
       e_dv_color_yuv, outframe_ptrs, outframe_pitches);
 
-  GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_TFF);
+  gst_video_frame_unmap (&frame);
+
+  GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_FLAG_TFF);
 
   GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buf);
   GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_END (buf);
@@ -479,8 +509,8 @@ skip:
   dvdec->video_offset++;
 
 done:
+  gst_buffer_unmap (buf, &map);
   gst_buffer_unref (buf);
-  gst_object_unref (dvdec);
 
   return ret;
 
@@ -534,7 +564,8 @@ gst_dvdec_change_state (GstElement * element, GstStateChange transition)
           dv_decoder_new (0, dvdec->clamp_luma, dvdec->clamp_chroma);
       dvdec->decoder->quality = qualities[dvdec->quality];
       dv_set_error_log (dvdec->decoder, NULL);
-      gst_segment_init (dvdec->segment, GST_FORMAT_UNDEFINED);
+      gst_video_info_init (&dvdec->vinfo);
+      gst_segment_init (&dvdec->segment, GST_FORMAT_UNDEFINED);
       dvdec->src_negotiated = FALSE;
       dvdec->sink_negotiated = FALSE;
       /* 
@@ -549,7 +580,7 @@ gst_dvdec_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:
@@ -557,6 +588,11 @@ gst_dvdec_change_state (GstElement * element, GstStateChange transition)
     case GST_STATE_CHANGE_PAUSED_TO_READY:
       dv_decoder_free (dvdec->decoder);
       dvdec->decoder = NULL;
+      if (dvdec->pool) {
+        gst_buffer_pool_set_active (dvdec->pool, FALSE);
+        gst_object_unref (dvdec->pool);
+        dvdec->pool = NULL;
+      }
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
       break;
index de8481d..0e52de0 100644 (file)
@@ -23,6 +23,8 @@
 
 
 #include <gst/gst.h>
+#include <gst/video/video.h>
+
 #include <libdv/dv.h>
 
 
@@ -63,6 +65,7 @@ struct _GstDVDec {
 
   /* input caps */
   gboolean       sink_negotiated;
+  GstVideoInfo   vinfo;
   gint           framerate_numerator;
   gint           framerate_denominator;
   gint           height;
@@ -78,7 +81,8 @@ struct _GstDVDec {
   gint           video_offset;
   gint           drop_factor;
 
-  GstSegment   *segment;
+  GstBufferPool *pool;
+  GstSegment     segment;
 };
 
 struct _GstDVDecClass {
index fe0617e..aecef4f 100644 (file)
@@ -123,25 +123,23 @@ static GstStaticPadTemplate video_src_temp = GST_STATIC_PAD_TEMPLATE ("video",
 static GstStaticPadTemplate audio_src_temp = GST_STATIC_PAD_TEMPLATE ("audio",
     GST_PAD_SRC,
     GST_PAD_SOMETIMES,
-    GST_STATIC_CAPS ("audio/x-raw-int, "
-        "depth = (int) 16, "
-        "width = (int) 16, "
-        "signed = (boolean) TRUE, "
-        "channels = (int) {2, 4}, "
-        "endianness = (int) " G_STRINGIFY (G_BYTE_ORDER) ", "
-        "rate = (int) { 32000, 44100, 48000 }")
+    GST_STATIC_CAPS ("audio/x-raw, "
+        "format = (string) " GST_AUDIO_NE (S16) ", "
+        "layout = (string) interleaved, "
+        "rate = (int) { 32000, 44100, 48000 }, " "channels = (int) {2, 4}")
     );
 
 
-GST_BOILERPLATE (GstDVDemux, gst_dvdemux, GstElement, GST_TYPE_ELEMENT);
+#define gst_dvdemux_parent_class parent_class
+G_DEFINE_TYPE (GstDVDemux, gst_dvdemux, GST_TYPE_ELEMENT);
 
 static void gst_dvdemux_finalize (GObject * object);
 
 /* query functions */
-static const GstQueryType *gst_dvdemux_get_src_query_types (GstPad * pad);
-static gboolean gst_dvdemux_src_query (GstPad * pad, GstQuery * query);
-static const GstQueryType *gst_dvdemux_get_sink_query_types (GstPad * pad);
-static gboolean gst_dvdemux_sink_query (GstPad * pad, GstQuery * query);
+static gboolean gst_dvdemux_src_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
+static gboolean gst_dvdemux_sink_query (GstPad * pad, GstObject * parent,
+    GstQuery * query);
 
 /* convert functions */
 static gboolean gst_dvdemux_sink_convert (GstDVDemux * demux,
@@ -153,44 +151,26 @@ static gboolean gst_dvdemux_src_convert (GstDVDemux * demux, GstPad * pad,
 
 /* event functions */
 static gboolean gst_dvdemux_send_event (GstElement * element, GstEvent * event);
-static gboolean gst_dvdemux_handle_src_event (GstPad * pad, GstEvent * event);
-static gboolean gst_dvdemux_handle_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_dvdemux_handle_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
+static gboolean gst_dvdemux_handle_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event);
 
 /* scheduling functions */
 static void gst_dvdemux_loop (GstPad * pad);
 static GstFlowReturn gst_dvdemux_flush (GstDVDemux * dvdemux);
-static GstFlowReturn gst_dvdemux_chain (GstPad * pad, GstBuffer * buffer);
+static GstFlowReturn gst_dvdemux_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buffer);
 
 /* state change functions */
-static gboolean gst_dvdemux_sink_activate (GstPad * sinkpad);
-static gboolean gst_dvdemux_sink_activate_push (GstPad * sinkpad,
-    gboolean active);
-static gboolean gst_dvdemux_sink_activate_pull (GstPad * sinkpad,
-    gboolean active);
+static gboolean gst_dvdemux_sink_activate (GstPad * sinkpad,
+    GstObject * parent);
+static gboolean gst_dvdemux_sink_activate_mode (GstPad * sinkpad,
+    GstObject * parent, GstPadMode mode, gboolean active);
 static GstStateChangeReturn gst_dvdemux_change_state (GstElement * element,
     GstStateChange transition);
 
 static void
-gst_dvdemux_base_init (gpointer g_class)
-{
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&sink_temp));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&video_src_temp));
-  gst_element_class_add_pad_template (element_class,
-      gst_static_pad_template_get (&audio_src_temp));
-
-  gst_element_class_set_details_simple (element_class,
-      "DV system stream demuxer", "Codec/Demuxer",
-      "Uses libdv to separate DV audio from DV video (libdv.sourceforge.net)",
-      "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
-
-  GST_DEBUG_CATEGORY_INIT (dvdemux_debug, "dvdemux", 0, "DV demuxer element");
-}
-
-static void
 gst_dvdemux_class_init (GstDVDemuxClass * klass)
 {
   GObjectClass *gobject_class;
@@ -203,10 +183,24 @@ gst_dvdemux_class_init (GstDVDemuxClass * klass)
 
   gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dvdemux_change_state);
   gstelement_class->send_event = GST_DEBUG_FUNCPTR (gst_dvdemux_send_event);
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sink_temp));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&video_src_temp));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&audio_src_temp));
+
+  gst_element_class_set_details_simple (gstelement_class,
+      "DV system stream demuxer", "Codec/Demuxer",
+      "Uses libdv to separate DV audio from DV video (libdv.sourceforge.net)",
+      "Erik Walthinsen <omega@cse.ogi.edu>, Wim Taymans <wim@fluendo.com>");
+
+  GST_DEBUG_CATEGORY_INIT (dvdemux_debug, "dvdemux", 0, "DV demuxer element");
 }
 
 static void
-gst_dvdemux_init (GstDVDemux * dvdemux, GstDVDemuxClass * g_class)
+gst_dvdemux_init (GstDVDemux * dvdemux)
 {
   gint i;
 
@@ -216,11 +210,8 @@ gst_dvdemux_init (GstDVDemux * dvdemux, GstDVDemuxClass * g_class)
   gst_pad_set_activate_function (dvdemux->sinkpad,
       GST_DEBUG_FUNCPTR (gst_dvdemux_sink_activate));
   /* the function to activate in push mode */
-  gst_pad_set_activatepush_function (dvdemux->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_dvdemux_sink_activate_push));
-  /* the function to activate in pull mode */
-  gst_pad_set_activatepull_function (dvdemux->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_dvdemux_sink_activate_pull));
+  gst_pad_set_activatemode_function (dvdemux->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_dvdemux_sink_activate_mode));
   /* for push mode, this is the chain function */
   gst_pad_set_chain_function (dvdemux->sinkpad,
       GST_DEBUG_FUNCPTR (gst_dvdemux_chain));
@@ -230,8 +221,6 @@ gst_dvdemux_init (GstDVDemux * dvdemux, GstDVDemuxClass * g_class)
   /* query functions */
   gst_pad_set_query_function (dvdemux->sinkpad,
       GST_DEBUG_FUNCPTR (gst_dvdemux_sink_query));
-  gst_pad_set_query_type_function (dvdemux->sinkpad,
-      GST_DEBUG_FUNCPTR (gst_dvdemux_get_sink_query_types));
 
   /* now add the pad */
   gst_element_add_pad (GST_ELEMENT (dvdemux), dvdemux->sinkpad);
@@ -296,8 +285,6 @@ gst_dvdemux_add_pad (GstDVDemux * dvdemux, GstStaticPadTemplate * template)
 
   gst_pad_set_query_function (pad, GST_DEBUG_FUNCPTR (gst_dvdemux_src_query));
 
-  gst_pad_set_query_type_function (pad,
-      GST_DEBUG_FUNCPTR (gst_dvdemux_get_src_query_types));
   gst_pad_set_event_function (pad,
       GST_DEBUG_FUNCPTR (gst_dvdemux_handle_src_event));
   gst_pad_use_fixed_caps (pad);
@@ -311,14 +298,12 @@ gst_dvdemux_add_pad (GstDVDemux * dvdemux, GstStaticPadTemplate * template)
   if (no_more_pads)
     gst_element_no_more_pads (GST_ELEMENT (dvdemux));
 
-  gst_pad_push_event (pad, gst_event_new_new_segment (FALSE,
-          dvdemux->byte_segment.rate, GST_FORMAT_TIME,
-          dvdemux->time_segment.start, dvdemux->time_segment.stop,
-          dvdemux->time_segment.start));
+  gst_pad_push_event (pad, gst_event_new_segment (&dvdemux->time_segment));
 
   if (no_more_pads) {
-    gst_element_found_tags (GST_ELEMENT (dvdemux),
-        gst_tag_list_new_full (GST_TAG_CONTAINER_FORMAT, "DV", NULL));
+    gst_pad_push_event (pad,
+        gst_event_new_tag (gst_tag_list_new (GST_TAG_CONTAINER_FORMAT, "DV",
+                NULL)));
   }
 
   return pad;
@@ -532,26 +517,13 @@ error:
   }
 }
 
-static const GstQueryType *
-gst_dvdemux_get_src_query_types (GstPad * pad)
-{
-  static const GstQueryType src_query_types[] = {
-    GST_QUERY_POSITION,
-    GST_QUERY_DURATION,
-    GST_QUERY_CONVERT,
-    0
-  };
-
-  return src_query_types;
-}
-
 static gboolean
-gst_dvdemux_src_query (GstPad * pad, GstQuery * query)
+gst_dvdemux_src_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
   gboolean res = TRUE;
   GstDVDemux *dvdemux;
 
-  dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
+  dvdemux = GST_DVDEMUX (parent);
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_POSITION:
@@ -564,7 +536,7 @@ gst_dvdemux_src_query (GstPad * pad, GstQuery * query)
 
       /* bring the position to the requested format. */
       if (!(res = gst_dvdemux_src_convert (dvdemux, pad,
-                  GST_FORMAT_TIME, dvdemux->time_segment.last_stop,
+                  GST_FORMAT_TIME, dvdemux->time_segment.position,
                   &format, &cur)))
         goto error;
       gst_query_set_position (query, format, cur);
@@ -618,40 +590,27 @@ gst_dvdemux_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 (dvdemux);
 
   return res;
 
   /* ERRORS */
 error:
   {
-    gst_object_unref (dvdemux);
     GST_DEBUG ("error source query");
     return FALSE;
   }
 }
 
-static const GstQueryType *
-gst_dvdemux_get_sink_query_types (GstPad * pad)
-{
-  static const GstQueryType sink_query_types[] = {
-    GST_QUERY_CONVERT,
-    0
-  };
-
-  return sink_query_types;
-}
-
 static gboolean
-gst_dvdemux_sink_query (GstPad * pad, GstQuery * query)
+gst_dvdemux_sink_query (GstPad * pad, GstObject * parent, GstQuery * query)
 {
   gboolean res = TRUE;
   GstDVDemux *dvdemux;
 
-  dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
+  dvdemux = GST_DVDEMUX (parent);
 
   switch (GST_QUERY_TYPE (query)) {
     case GST_QUERY_CONVERT:
@@ -668,17 +627,15 @@ gst_dvdemux_sink_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 (dvdemux);
 
   return res;
 
   /* ERRORS */
 error:
   {
-    gst_object_unref (dvdemux);
     GST_DEBUG ("error handling sink query");
     return FALSE;
   }
@@ -704,9 +661,10 @@ gst_dvdemux_push_event (GstDVDemux * dvdemux, GstEvent * event)
 }
 
 static gboolean
-gst_dvdemux_handle_sink_event (GstPad * pad, GstEvent * event)
+gst_dvdemux_handle_sink_event (GstPad * pad, GstObject * parent,
+    GstEvent * event)
 {
-  GstDVDemux *dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
+  GstDVDemux *dvdemux = GST_DVDEMUX (parent);
   gboolean res = TRUE;
 
   switch (GST_EVENT_TYPE (event)) {
@@ -723,29 +681,24 @@ gst_dvdemux_handle_sink_event (GstPad * pad, GstEvent * event)
       gst_segment_init (&dvdemux->time_segment, GST_FORMAT_TIME);
       res = gst_dvdemux_push_event (dvdemux, event);
       break;
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
     {
-      gboolean update;
-      gdouble rate;
-      GstFormat format;
-      gint64 start, stop, time;
-
-      /* parse byte start and stop positions */
-      gst_event_parse_new_segment (event, &update, &rate, &format,
-          &start, &stop, &time);
+      const GstSegment *segment;
 
-      switch (format) {
+      gst_event_parse_segment (event, &segment);
+      switch (segment->format) {
         case GST_FORMAT_BYTES:
-          gst_segment_set_newsegment (&dvdemux->byte_segment, update,
-              rate, format, start, stop, time);
+          gst_segment_copy_into (segment, &dvdemux->byte_segment);
 
+#if 0
+          /* FIXME ?? no longer such subtle distinction in 0.11 */
           /* the update can always be sent */
           if (update) {
             GstEvent *update;
 
             update = gst_event_new_new_segment (TRUE,
                 dvdemux->time_segment.rate, dvdemux->time_segment.format,
-                dvdemux->time_segment.start, dvdemux->time_segment.last_stop,
+                dvdemux->time_segment.start, dvdemux->time_segment.position,
                 dvdemux->time_segment.time);
 
             gst_dvdemux_push_event (dvdemux, update);
@@ -755,11 +708,12 @@ gst_dvdemux_handle_sink_event (GstPad * pad, GstEvent * event)
              * frames, etc.. */
             dvdemux->need_segment = TRUE;
           }
+#endif
+          dvdemux->need_segment = TRUE;
           gst_event_unref (event);
           break;
         case GST_FORMAT_TIME:
-          gst_segment_set_newsegment (&dvdemux->time_segment, update,
-              rate, format, start, stop, time);
+          gst_segment_copy_into (segment, &dvdemux->time_segment);
 
           /* and we can just forward this time event */
           res = gst_dvdemux_push_event (dvdemux, event);
@@ -780,13 +734,14 @@ gst_dvdemux_handle_sink_event (GstPad * pad, GstEvent * event)
       /* and clear the adapter */
       gst_adapter_clear (dvdemux->adapter);
       break;
+    case GST_EVENT_CAPS:
+      gst_event_unref (event);
+      break;
     default:
       res = gst_dvdemux_push_event (dvdemux, event);
       break;
   }
 
-  gst_object_unref (dvdemux);
-
   return res;
 }
 
@@ -947,22 +902,25 @@ gst_dvdemux_do_seek (GstDVDemux * demux, GstSegment * segment)
    * timestamp can be found. */
   format = GST_FORMAT_BYTES;
   res = gst_dvdemux_sink_convert (demux,
-      segment->format, segment->last_stop,
-      &format, &demux->byte_segment.last_stop);
+      segment->format, segment->position,
+      &format, (gint64 *) & demux->byte_segment.position);
   if (!res)
     goto done;
 
   /* update byte segment start */
   gst_dvdemux_sink_convert (demux,
-      segment->format, segment->start, &format, &demux->byte_segment.start);
+      segment->format, segment->start, &format,
+      (gint64 *) & demux->byte_segment.start);
 
   /* update byte segment stop */
   gst_dvdemux_sink_convert (demux,
-      segment->format, segment->stop, &format, &demux->byte_segment.stop);
+      segment->format, segment->stop, &format,
+      (gint64 *) & demux->byte_segment.stop);
 
   /* update byte segment time */
   gst_dvdemux_sink_convert (demux,
-      segment->format, segment->time, &format, &demux->byte_segment.time);
+      segment->format, segment->time, &format,
+      (gint64 *) & demux->byte_segment.time);
 
   /* calculate current frame number */
   format = GST_FORMAT_DEFAULT;
@@ -1043,34 +1001,22 @@ gst_dvdemux_handle_pull_seek (GstDVDemux * demux, GstPad * pad,
 
   /* now configure the seek segment */
   if (event) {
-    gst_segment_set_seek (&seeksegment, rate, format, flags,
+    gst_segment_do_seek (&seeksegment, rate, format, flags,
         cur_type, cur, stop_type, stop, &update);
   }
 
   GST_DEBUG_OBJECT (demux, "segment configured from %" G_GINT64_FORMAT
       " to %" G_GINT64_FORMAT ", position %" G_GINT64_FORMAT,
-      seeksegment.start, seeksegment.stop, seeksegment.last_stop);
+      seeksegment.start, seeksegment.stop, seeksegment.position);
 
-  /* do the seek, segment.last_stop contains new position. */
+  /* do the seek, segment.position contains new position. */
   res = gst_dvdemux_do_seek (demux, &seeksegment);
 
   /* and prepare to continue streaming */
   if (flush) {
     /* send flush stop, peer will accept data and events again. We
      * are not yet providing data as we still have the STREAM_LOCK. */
-    gst_dvdemux_push_event (demux, gst_event_new_flush_stop ());
-  } else if (res && demux->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 (demux, "closing running segment %" G_GINT64_FORMAT
-        " to %" G_GINT64_FORMAT, demux->time_segment.start,
-        demux->time_segment.last_stop);
-
-    gst_dvdemux_push_event (demux,
-        gst_event_new_new_segment (TRUE,
-            demux->time_segment.rate, demux->time_segment.format,
-            demux->time_segment.start, demux->time_segment.last_stop,
-            demux->time_segment.time));
+    gst_dvdemux_push_event (demux, gst_event_new_flush_stop (TRUE));
   }
 
   /* if successfull seek, we update our real segment and push
@@ -1081,7 +1027,7 @@ gst_dvdemux_handle_pull_seek (GstDVDemux * demux, GstPad * pad,
     if (demux->time_segment.flags & GST_SEEK_FLAG_SEGMENT) {
       gst_element_post_message (GST_ELEMENT_CAST (demux),
           gst_message_new_segment_start (GST_OBJECT_CAST (demux),
-              demux->time_segment.format, demux->time_segment.last_stop));
+              demux->time_segment.format, demux->time_segment.position));
     }
     if ((stop = demux->time_segment.stop) == -1)
       stop = demux->time_segment.duration;
@@ -1092,14 +1038,11 @@ gst_dvdemux_handle_pull_seek (GstDVDemux * demux, GstPad * pad,
     if (demux->pending_segment)
       gst_event_unref (demux->pending_segment);
 
-    demux->pending_segment = gst_event_new_new_segment (FALSE,
-        demux->time_segment.rate, demux->time_segment.format,
-        demux->time_segment.last_stop, stop, demux->time_segment.time);
+    demux->pending_segment = gst_event_new_segment (&demux->time_segment);
 
     demux->need_segment = FALSE;
   }
 
-  demux->running = TRUE;
   /* and restart the task in case it got paused explicitely or by
    * the FLUSH_START event we pushed out. */
   gst_pad_start_task (demux->sinkpad, (GstTaskFunction) gst_dvdemux_loop,
@@ -1166,12 +1109,13 @@ gst_dvdemux_send_event (GstElement * element, GstEvent * event)
 
 /* handle an event on the source pad, it's most likely a seek */
 static gboolean
-gst_dvdemux_handle_src_event (GstPad * pad, GstEvent * event)
+gst_dvdemux_handle_src_event (GstPad * pad, GstObject * parent,
+    GstEvent * event)
 {
   gboolean res = TRUE;
   GstDVDemux *dvdemux;
 
-  dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
+  dvdemux = GST_DVDEMUX (parent);
 
   switch (GST_EVENT_TYPE (event)) {
     case GST_EVENT_SEEK:
@@ -1186,7 +1130,8 @@ gst_dvdemux_handle_src_event (GstPad * pad, GstEvent * event)
       res = FALSE;
       break;
     case GST_EVENT_NAVIGATION:
-      /* no navigation either... */
+    case GST_EVENT_CAPS:
+      /* no navigation or caps either... */
       res = FALSE;
       break;
     default:
@@ -1197,8 +1142,6 @@ gst_dvdemux_handle_src_event (GstPad * pad, GstEvent * event)
   if (event)
     gst_event_unref (event);
 
-  gst_object_unref (dvdemux);
-
   return res;
 }
 
@@ -1209,11 +1152,11 @@ gst_dvdemux_demux_audio (GstDVDemux * dvdemux, GstBuffer * buffer,
 {
   gint num_samples;
   GstFlowReturn ret;
-  const guint8 *data;
+  GstMapInfo map;
 
-  data = GST_BUFFER_DATA (buffer);
-
-  dv_decode_full_audio (dvdemux->decoder, data, dvdemux->audio_buffers);
+  gst_buffer_map (buffer, &map, GST_MAP_READ);
+  dv_decode_full_audio (dvdemux->decoder, map.data, dvdemux->audio_buffers);
+  gst_buffer_unmap (buffer, &map);
 
   if (G_LIKELY ((num_samples = dv_get_num_samples (dvdemux->decoder)) > 0)) {
     gint16 *a_ptr;
@@ -1231,18 +1174,15 @@ gst_dvdemux_demux_audio (GstDVDemux * dvdemux, GstBuffer * buffer,
     if (G_UNLIKELY ((frequency != dvdemux->frequency)
             || (channels != dvdemux->channels))) {
       GstCaps *caps;
+      GstAudioInfo info;
 
       dvdemux->frequency = frequency;
       dvdemux->channels = channels;
 
-      /* and set new caps */
-      caps = gst_caps_new_simple ("audio/x-raw-int",
-          "rate", G_TYPE_INT, frequency,
-          "depth", G_TYPE_INT, 16,
-          "width", G_TYPE_INT, 16,
-          "signed", G_TYPE_BOOLEAN, TRUE,
-          "channels", G_TYPE_INT, channels,
-          "endianness", G_TYPE_INT, G_BYTE_ORDER, NULL);
+      gst_audio_info_init (&info);
+      gst_audio_info_set_format (&info, GST_AUDIO_FORMAT_S16LE,
+          frequency, channels, NULL);
+      caps = gst_audio_info_to_caps (&info);
       gst_pad_set_caps (dvdemux->audiosrcpad, caps);
       gst_caps_unref (caps);
     }
@@ -1250,18 +1190,20 @@ gst_dvdemux_demux_audio (GstDVDemux * dvdemux, GstBuffer * buffer,
     outbuf = gst_buffer_new_and_alloc (num_samples *
         sizeof (gint16) * dvdemux->channels);
 
-    a_ptr = (gint16 *) GST_BUFFER_DATA (outbuf);
+    gst_buffer_map (outbuf, &map, GST_MAP_WRITE);
+    a_ptr = (gint16 *) map.data;
 
     for (i = 0; i < num_samples; i++) {
       for (j = 0; j < dvdemux->channels; j++) {
         *(a_ptr++) = dvdemux->audio_buffers[j][i];
       }
     }
+    gst_buffer_unmap (outbuf, &map);
 
     GST_DEBUG ("pushing audio %" GST_TIME_FORMAT,
-        GST_TIME_ARGS (dvdemux->time_segment.last_stop));
+        GST_TIME_ARGS (dvdemux->time_segment.position));
 
-    GST_BUFFER_TIMESTAMP (outbuf) = dvdemux->time_segment.last_stop;
+    GST_BUFFER_TIMESTAMP (outbuf) = dvdemux->time_segment.position;
     GST_BUFFER_DURATION (outbuf) = duration;
     GST_BUFFER_OFFSET (outbuf) = dvdemux->audio_offset;
     dvdemux->audio_offset += num_samples;
@@ -1269,7 +1211,6 @@ gst_dvdemux_demux_audio (GstDVDemux * dvdemux, GstBuffer * buffer,
 
     if (dvdemux->new_media)
       GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
-    gst_buffer_set_caps (outbuf, GST_PAD_CAPS (dvdemux->audiosrcpad));
 
     ret = gst_pad_push (dvdemux->audiosrcpad, outbuf);
   } else {
@@ -1337,19 +1278,18 @@ gst_dvdemux_demux_video (GstDVDemux * dvdemux, GstBuffer * buffer,
 
   /* takes ownership of buffer here, we just need to modify
    * the metadata. */
-  outbuf = gst_buffer_make_metadata_writable (buffer);
+  outbuf = gst_buffer_make_writable (buffer);
 
-  GST_BUFFER_TIMESTAMP (outbuf) = dvdemux->time_segment.last_stop;
+  GST_BUFFER_TIMESTAMP (outbuf) = dvdemux->time_segment.position;
   GST_BUFFER_OFFSET (outbuf) = dvdemux->video_offset;
   GST_BUFFER_OFFSET_END (outbuf) = dvdemux->video_offset + 1;
   GST_BUFFER_DURATION (outbuf) = duration;
 
   if (dvdemux->new_media)
     GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
-  gst_buffer_set_caps (outbuf, GST_PAD_CAPS (dvdemux->videosrcpad));
 
   GST_DEBUG ("pushing video %" GST_TIME_FORMAT,
-      GST_TIME_ARGS (dvdemux->time_segment.last_stop));
+      GST_TIME_ARGS (dvdemux->time_segment.position));
 
   ret = gst_pad_push (dvdemux->videosrcpad, outbuf);
 
@@ -1375,11 +1315,14 @@ static gboolean
 gst_dvdemux_get_timecode (GstDVDemux * dvdemux, GstBuffer * buffer,
     GstSMPTETimeCode * timecode)
 {
-  guint8 *data = GST_BUFFER_DATA (buffer);
+  guint8 *data;
+  GstMapInfo map;
   int offset;
   int dif;
   int n_difs = dvdemux->decoder->num_dif_seqs;
 
+  gst_buffer_map (buffer, &map, GST_MAP_READ);
+  data = map.data;
   for (dif = 0; dif < n_difs; dif++) {
     offset = get_ssyb_offset (dif, 3);
     if (data[offset + 3] == 0x13) {
@@ -1393,23 +1336,28 @@ gst_dvdemux_get_timecode (GstDVDemux * dvdemux, GstBuffer * buffer,
           (data[offset + 7] & 0xf);
       GST_DEBUG ("got timecode %" GST_SMPTE_TIME_CODE_FORMAT,
           GST_SMPTE_TIME_CODE_ARGS (timecode));
+      gst_buffer_unmap (buffer, &map);
       return TRUE;
     }
   }
 
+  gst_buffer_unmap (buffer, &map);
   return FALSE;
 }
 
 static gboolean
 gst_dvdemux_is_new_media (GstDVDemux * dvdemux, GstBuffer * buffer)
 {
-  guint8 *data = GST_BUFFER_DATA (buffer);
+  guint8 *data;
+  GstMapInfo map;
   int aaux_offset;
   int dif;
   int n_difs;
 
   n_difs = dvdemux->decoder->num_dif_seqs;
 
+  gst_buffer_map (buffer, &map, GST_MAP_READ);
+  data = map.data;
   for (dif = 0; dif < n_difs; dif++) {
     if (dif & 1) {
       aaux_offset = (dif * 12000) + (6 + 16 * 1) * 80 + 3;
@@ -1417,11 +1365,14 @@ gst_dvdemux_is_new_media (GstDVDemux * dvdemux, GstBuffer * buffer)
       aaux_offset = (dif * 12000) + (6 + 16 * 4) * 80 + 3;
     }
     if (data[aaux_offset + 0] == 0x51) {
-      if ((data[aaux_offset + 2] & 0x80) == 0)
+      if ((data[aaux_offset + 2] & 0x80) == 0) {
+        gst_buffer_unmap (buffer, &map);
         return TRUE;
+      }
     }
   }
 
+  gst_buffer_unmap (buffer, &map);
   return FALSE;
 }
 
@@ -1431,13 +1382,12 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer)
 {
   GstClockTime next_ts;
   GstFlowReturn aret, vret, ret;
-  guint8 *data;
+  GstMapInfo map;
   guint64 duration;
   GstSMPTETimeCode timecode;
   int frame_number;
 
   if (G_UNLIKELY (dvdemux->need_segment)) {
-    GstEvent *event;
     GstFormat format;
 
     /* convert to time and store as start/end_timestamp */
@@ -1445,12 +1395,12 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer)
     if (!(gst_dvdemux_convert_sink_pair (dvdemux,
                 GST_FORMAT_BYTES, dvdemux->byte_segment.start,
                 dvdemux->byte_segment.stop, format,
-                &dvdemux->time_segment.start, &dvdemux->time_segment.stop)))
+                (gint64 *) & dvdemux->time_segment.start,
+                (gint64 *) & dvdemux->time_segment.stop)))
       goto segment_error;
 
     dvdemux->time_segment.rate = dvdemux->byte_segment.rate;
-    dvdemux->time_segment.abs_rate = dvdemux->byte_segment.abs_rate;
-    dvdemux->time_segment.last_stop = dvdemux->time_segment.start;
+    dvdemux->time_segment.position = dvdemux->time_segment.start;
 
     /* calculate current frame number */
     format = GST_FORMAT_DEFAULT;
@@ -1465,10 +1415,8 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer)
         GST_TIME_ARGS (dvdemux->time_segment.stop),
         GST_TIME_ARGS (dvdemux->time_segment.start));
 
-    event = gst_event_new_new_segment (FALSE, dvdemux->byte_segment.rate,
-        GST_FORMAT_TIME, dvdemux->time_segment.start,
-        dvdemux->time_segment.stop, dvdemux->time_segment.start);
-    gst_dvdemux_push_event (dvdemux, event);
+    gst_dvdemux_push_event (dvdemux,
+        gst_event_new_segment (&dvdemux->time_segment));
 
     dvdemux->need_segment = FALSE;
   }
@@ -1482,11 +1430,11 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer)
   next_ts = gst_util_uint64_scale_int (
       (dvdemux->frame_offset + 1) * GST_SECOND,
       dvdemux->framerate_denominator, dvdemux->framerate_numerator);
-  duration = next_ts - dvdemux->time_segment.last_stop;
-
-  data = GST_BUFFER_DATA (buffer);
+  duration = next_ts - dvdemux->time_segment.position;
 
-  dv_parse_packs (dvdemux->decoder, data);
+  gst_buffer_map (buffer, &map, GST_MAP_READ);
+  dv_parse_packs (dvdemux->decoder, map.data);
+  gst_buffer_unmap (buffer, &map);
   dvdemux->new_media = FALSE;
   if (gst_dvdemux_is_new_media (dvdemux, buffer) &&
       dvdemux->frames_since_new_media > 2) {
@@ -1513,7 +1461,7 @@ gst_dvdemux_demux_frame (GstDVDemux * dvdemux, GstBuffer * buffer)
     goto done;
   }
 
-  gst_segment_set_last_stop (&dvdemux->time_segment, GST_FORMAT_TIME, next_ts);
+  dvdemux->time_segment.position = next_ts;
   dvdemux->frame_offset++;
 
   /* check for the end of the segment */
@@ -1545,11 +1493,14 @@ gst_dvdemux_flush (GstDVDemux * dvdemux)
     gint length;
 
     /* get the accumulated bytes */
-    data = gst_adapter_peek (dvdemux->adapter, dvdemux->frame_len);
+    data = gst_adapter_map (dvdemux->adapter, dvdemux->frame_len);
 
     /* parse header to know the length and other params */
-    if (G_UNLIKELY (dv_parse_header (dvdemux->decoder, data) < 0))
+    if (G_UNLIKELY (dv_parse_header (dvdemux->decoder, data) < 0)) {
+      gst_adapter_unmap (dvdemux->adapter);
       goto parse_header_error;
+    }
+    gst_adapter_unmap (dvdemux->adapter);
 
     /* after parsing the header we know the length of the data */
     length = dvdemux->frame_len = dvdemux->decoder->frame_size;
@@ -1569,13 +1520,7 @@ gst_dvdemux_flush (GstDVDemux * dvdemux)
     if (G_LIKELY (gst_adapter_available (dvdemux->adapter) >= length)) {
       GstBuffer *buffer;
 
-      data = gst_adapter_take (dvdemux->adapter, length);
-
-      /* create buffer for the remainder of the code */
-      buffer = gst_buffer_new ();
-      GST_BUFFER_DATA (buffer) = (guint8 *) data;
-      GST_BUFFER_SIZE (buffer) = length;
-      GST_BUFFER_MALLOCDATA (buffer) = (guint8 *) data;
+      buffer = gst_adapter_take_buffer (dvdemux->adapter, length);
 
       /* and decode the buffer, takes ownership */
       ret = gst_dvdemux_demux_frame (dvdemux, buffer);
@@ -1600,13 +1545,13 @@ parse_header_error:
  * accumulate data until we have a frame, then decode. 
  */
 static GstFlowReturn
-gst_dvdemux_chain (GstPad * pad, GstBuffer * buffer)
+gst_dvdemux_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer)
 {
   GstDVDemux *dvdemux;
   GstFlowReturn ret;
   GstClockTime timestamp;
 
-  dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
+  dvdemux = GST_DVDEMUX (parent);
 
   /* a discontinuity in the stream, we need to get rid of
    * accumulated data in the adapter and assume a new frame
@@ -1617,8 +1562,7 @@ gst_dvdemux_chain (GstPad * pad, GstBuffer * buffer)
   /* a timestamp always should be respected */
   timestamp = GST_BUFFER_TIMESTAMP (buffer);
   if (GST_CLOCK_TIME_IS_VALID (timestamp)) {
-    gst_segment_set_last_stop (&dvdemux->time_segment, GST_FORMAT_TIME,
-        timestamp);
+    dvdemux->time_segment.position = timestamp;
     /* FIXME, adjust frame_offset and other counters */
   }
 
@@ -1637,8 +1581,6 @@ gst_dvdemux_chain (GstPad * pad, GstBuffer * buffer)
   /* and try to flush pending frames */
   ret = gst_dvdemux_flush (dvdemux);
 
-  gst_object_unref (dvdemux);
-
   return ret;
 }
 
@@ -1653,7 +1595,7 @@ gst_dvdemux_loop (GstPad * pad)
   GstFlowReturn ret;
   GstDVDemux *dvdemux;
   GstBuffer *buffer = NULL;
-  const guint8 *data;
+  GstMapInfo map;
 
   dvdemux = GST_DVDEMUX (gst_pad_get_parent (pad));
 
@@ -1662,19 +1604,21 @@ gst_dvdemux_loop (GstPad * pad)
     /* pull in NTSC sized buffer to figure out the frame
      * length */
     ret = gst_pad_pull_range (dvdemux->sinkpad,
-        dvdemux->byte_segment.last_stop, NTSC_BUFFER, &buffer);
+        dvdemux->byte_segment.position, NTSC_BUFFER, &buffer);
     if (G_UNLIKELY (ret != GST_FLOW_OK))
       goto pause;
 
     /* check buffer size, don't want to read small buffers */
-    if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < NTSC_BUFFER))
+    if (G_UNLIKELY (gst_buffer_get_size (buffer) < NTSC_BUFFER))
       goto small_buffer;
 
-    data = GST_BUFFER_DATA (buffer);
-
+    gst_buffer_map (buffer, &map, GST_MAP_READ);
     /* parse header to know the length and other params */
-    if (G_UNLIKELY (dv_parse_header (dvdemux->decoder, data) < 0))
+    if (G_UNLIKELY (dv_parse_header (dvdemux->decoder, map.data) < 0)) {
+      gst_buffer_unmap (buffer, &map);
       goto parse_header_error;
+    }
+    gst_buffer_unmap (buffer, &map);
 
     /* after parsing the header we know the length of the data */
     dvdemux->frame_len = dvdemux->decoder->frame_size;
@@ -1736,15 +1680,15 @@ gst_dvdemux_loop (GstPad * pad)
 
   if (G_LIKELY (buffer == NULL)) {
     GST_DEBUG_OBJECT (dvdemux, "pulling buffer at offset %" G_GINT64_FORMAT,
-        dvdemux->byte_segment.last_stop);
+        dvdemux->byte_segment.position);
 
     ret = gst_pad_pull_range (dvdemux->sinkpad,
-        dvdemux->byte_segment.last_stop, dvdemux->frame_len, &buffer);
+        dvdemux->byte_segment.position, dvdemux->frame_len, &buffer);
     if (ret != GST_FLOW_OK)
       goto pause;
 
     /* check buffer size, don't want to read small buffers */
-    if (GST_BUFFER_SIZE (buffer) < dvdemux->frame_len)
+    if (gst_buffer_get_size (buffer) < dvdemux->frame_len)
       goto small_buffer;
   }
   /* and decode the buffer */
@@ -1753,7 +1697,7 @@ gst_dvdemux_loop (GstPad * pad)
     goto pause;
 
   /* and position ourselves for the next buffer */
-  dvdemux->byte_segment.last_stop += dvdemux->frame_len;
+  dvdemux->byte_segment.position += dvdemux->frame_len;
 
 done:
   gst_object_unref (dvdemux);
@@ -1766,7 +1710,6 @@ parse_header_error:
     GST_ELEMENT_ERROR (dvdemux, STREAM, DECODE,
         (NULL), ("Error parsing DV header"));
     gst_buffer_unref (buffer);
-    dvdemux->running = FALSE;
     gst_pad_pause_task (dvdemux->sinkpad);
     gst_dvdemux_push_event (dvdemux, gst_event_new_eos ());
     goto done;
@@ -1776,7 +1719,6 @@ small_buffer:
     GST_ELEMENT_ERROR (dvdemux, STREAM, DECODE,
         (NULL), ("Error reading buffer"));
     gst_buffer_unref (buffer);
-    dvdemux->running = FALSE;
     gst_pad_pause_task (dvdemux->sinkpad);
     gst_dvdemux_push_event (dvdemux, gst_event_new_eos ());
     goto done;
@@ -1784,15 +1726,21 @@ small_buffer:
 pause:
   {
     GST_INFO_OBJECT (dvdemux, "pausing task, %s", gst_flow_get_name (ret));
-    dvdemux->running = FALSE;
     gst_pad_pause_task (dvdemux->sinkpad);
     if (ret == GST_FLOW_EOS) {
       GST_LOG_OBJECT (dvdemux, "got eos");
+      /* so align our position with the end of it, if there is one
+       * this ensures a subsequent will arrive at correct base/acc time */
+      if (dvdemux->time_segment.rate > 0.0 &&
+          GST_CLOCK_TIME_IS_VALID (dvdemux->time_segment.stop))
+        dvdemux->time_segment.position = dvdemux->time_segment.stop;
+      else if (dvdemux->time_segment.rate < 0.0)
+        dvdemux->time_segment.position = dvdemux->time_segment.start;
       /* perform EOS logic */
       if (dvdemux->time_segment.flags & GST_SEEK_FLAG_SEGMENT) {
         gst_element_post_message (GST_ELEMENT (dvdemux),
             gst_message_new_segment_done (GST_OBJECT_CAST (dvdemux),
-                dvdemux->time_segment.format, dvdemux->time_segment.last_stop));
+                dvdemux->time_segment.format, dvdemux->time_segment.position));
       } else {
         gst_dvdemux_push_event (dvdemux, gst_event_new_eos ());
       }
@@ -1807,53 +1755,69 @@ pause:
 }
 
 static gboolean
-gst_dvdemux_sink_activate_push (GstPad * sinkpad, gboolean active)
+gst_dvdemux_sink_activate_mode (GstPad * sinkpad, GstObject * parent,
+    GstPadMode mode, gboolean active)
 {
-  GstDVDemux *demux = GST_DVDEMUX (gst_pad_get_parent (sinkpad));
-
-  if (active) {
-    demux->seek_handler = gst_dvdemux_handle_push_seek;
-  } else {
-    demux->seek_handler = NULL;
+  gboolean res;
+  GstDVDemux *demux = GST_DVDEMUX (parent);
+
+  switch (mode) {
+    case GST_PAD_MODE_PULL:
+      if (active) {
+        demux->seek_handler = gst_dvdemux_handle_pull_seek;
+        res = gst_pad_start_task (sinkpad,
+            (GstTaskFunction) gst_dvdemux_loop, sinkpad);
+      } else {
+        demux->seek_handler = NULL;
+        res = gst_pad_stop_task (sinkpad);
+      }
+      break;
+    case GST_PAD_MODE_PUSH:
+      if (active) {
+        GST_DEBUG_OBJECT (demux, "activating push/chain function");
+        demux->seek_handler = gst_dvdemux_handle_push_seek;
+      } else {
+        GST_DEBUG_OBJECT (demux, "deactivating push/chain function");
+        demux->seek_handler = NULL;
+      }
+      res = TRUE;
+      break;
+    default:
+      res = FALSE;
+      break;
   }
-  gst_object_unref (demux);
-
-  return TRUE;
+  return res;
 }
 
+/* decide on push or pull based scheduling */
 static gboolean
-gst_dvdemux_sink_activate_pull (GstPad * sinkpad, gboolean active)
+gst_dvdemux_sink_activate (GstPad * sinkpad, GstObject * parent)
 {
-  GstDVDemux *demux = GST_DVDEMUX (gst_pad_get_parent (sinkpad));
+  GstQuery *query;
+  gboolean pull_mode;
 
-  if (active) {
-    demux->running = TRUE;
-    demux->seek_handler = gst_dvdemux_handle_pull_seek;
-    gst_pad_start_task (sinkpad, (GstTaskFunction) gst_dvdemux_loop, sinkpad);
-  } else {
-    demux->seek_handler = NULL;
-    gst_pad_stop_task (sinkpad);
-    demux->running = FALSE;
+  query = gst_query_new_scheduling ();
+
+  if (!gst_pad_peer_query (sinkpad, query)) {
+    gst_query_unref (query);
+    goto activate_push;
   }
 
-  gst_object_unref (demux);
+  pull_mode = gst_query_has_scheduling_mode (query, GST_PAD_MODE_PULL);
+  gst_query_unref (query);
 
-  return TRUE;
-};
+  if (!pull_mode)
+    goto activate_push;
 
-/* decide on push or pull based scheduling */
-static gboolean
-gst_dvdemux_sink_activate (GstPad * sinkpad)
-{
-  gboolean ret;
+  GST_DEBUG_OBJECT (sinkpad, "activating pull");
+  return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE);
 
-  if (gst_pad_check_pull_range (sinkpad))
-    ret = gst_pad_activate_pull (sinkpad, TRUE);
-  else
-    ret = gst_pad_activate_push (sinkpad, TRUE);
-
-  return ret;
-};
+activate_push:
+  {
+    GST_DEBUG_OBJECT (sinkpad, "activating push");
+    return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE);
+  }
+}
 
 static GstStateChangeReturn
 gst_dvdemux_change_state (GstElement * element, GstStateChange transition)
@@ -1875,7 +1839,7 @@ gst_dvdemux_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:
index 9a4173d..9303e4d 100644 (file)
@@ -75,7 +75,6 @@ struct _GstDVDemux {
   GstDVDemuxSeekHandler seek_handler;
   GstSegment     byte_segment;
   GstSegment     time_segment;
-  gboolean       running;
   gboolean       need_segment;
   gboolean       new_media;
   int            frames_since_new_media;