Merge branch 'master' into 0.11
[platform/upstream/gstreamer.git] / ext / ogg / gstoggdemux.c
index c883d12..31d4255 100644 (file)
@@ -134,7 +134,6 @@ static void gst_ogg_pad_finalize (GObject * object);
 static const GstQueryType *gst_ogg_pad_query_types (GstPad * pad);
 static gboolean gst_ogg_pad_src_query (GstPad * pad, GstQuery * query);
 static gboolean gst_ogg_pad_event (GstPad * pad, GstEvent * event);
-static GstCaps *gst_ogg_pad_getcaps (GstPad * pad);
 static GstOggPad *gst_ogg_chain_get_stream (GstOggChain * chain,
     guint32 serialno);
 
@@ -169,12 +168,11 @@ gst_ogg_pad_init (GstOggPad * pad)
 {
   gst_pad_set_event_function (GST_PAD (pad),
       GST_DEBUG_FUNCPTR (gst_ogg_pad_event));
-  gst_pad_set_getcaps_function (GST_PAD (pad),
-      GST_DEBUG_FUNCPTR (gst_ogg_pad_getcaps));
   gst_pad_set_query_type_function (GST_PAD (pad),
       GST_DEBUG_FUNCPTR (gst_ogg_pad_query_types));
   gst_pad_set_query_function (GST_PAD (pad),
       GST_DEBUG_FUNCPTR (gst_ogg_pad_src_query));
+  gst_pad_use_fixed_caps (GST_PAD (pad));
 
   pad->mode = GST_OGG_PAD_MODE_INIT;
 
@@ -183,7 +181,7 @@ gst_ogg_pad_init (GstOggPad * pad)
 
   pad->start_time = GST_CLOCK_TIME_NONE;
 
-  pad->last_stop = GST_CLOCK_TIME_NONE;
+  pad->position = GST_CLOCK_TIME_NONE;
 
   pad->have_type = FALSE;
   pad->continued = NULL;
@@ -255,12 +253,6 @@ gst_ogg_pad_query_types (GstPad * pad)
   return query_types;
 }
 
-static GstCaps *
-gst_ogg_pad_getcaps (GstPad * pad)
-{
-  return gst_caps_ref (GST_PAD_CAPS (pad));
-}
-
 static gboolean
 gst_ogg_pad_src_query (GstPad * pad, GstQuery * query)
 {
@@ -442,7 +434,7 @@ gst_ogg_pad_reset (GstOggPad * pad)
   pad->continued = NULL;
 
   pad->last_ret = GST_FLOW_OK;
-  pad->last_stop = GST_CLOCK_TIME_NONE;
+  pad->position = GST_CLOCK_TIME_NONE;
   pad->current_granule = -1;
   pad->keyframe_granule = -1;
   pad->is_eos = FALSE;
@@ -625,14 +617,14 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
     goto not_added;
 
   buf = gst_buffer_new_and_alloc (packet->bytes - offset - trim);
-  gst_buffer_set_caps (buf, GST_PAD_CAPS (pad));
 
   /* set delta flag for OGM content */
   if (delta_unit)
     GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT);
 
   /* copy packet in buffer */
-  memcpy (buf->data, packet->packet + offset, packet->bytes - offset - trim);
+  gst_buffer_fill (buf, 0, packet->packet + offset,
+      packet->bytes - offset - trim);
 
   GST_BUFFER_TIMESTAMP (buf) = out_timestamp;
   GST_BUFFER_DURATION (buf) = out_duration;
@@ -645,7 +637,7 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
     pad->discont = FALSE;
   }
 
-  pad->last_stop = ogg->segment.last_stop;
+  pad->position = ogg->segment.position;
 
   /* don't push the header packets when we are asked to skip them */
   if (!packet->b_o_s || push_headers) {
@@ -662,7 +654,7 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
 
   /* check if valid granulepos, then we can calculate the current
    * position. We know the granule for each packet but we only want to update
-   * the last_stop when we have a valid granulepos on the packet because else
+   * the position when we have a valid granulepos on the packet because else
    * our time jumps around for the different streams. */
   if (packet->granulepos < 0)
     goto done;
@@ -682,7 +674,7 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
   }
 
   /* and store as the current position */
-  gst_segment_set_last_stop (&ogg->segment, GST_FORMAT_TIME, current_time);
+  ogg->segment.position = current_time;
 
   GST_DEBUG_OBJECT (ogg, "ogg current time %" GST_TIME_FORMAT,
       GST_TIME_ARGS (current_time));
@@ -954,6 +946,7 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
 
         if (start_time != G_MAXUINT64) {
           gint64 segment_time;
+          GstSegment segment;
 
           GST_DEBUG_OBJECT (ogg, "start_time:  %" GST_TIME_FORMAT,
               GST_TIME_ARGS (start_time));
@@ -965,6 +958,8 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
             segment_time = chain->begin_time;
 
           /* create the newsegment event we are going to send out */
+          gst_segment_init (&segment, GST_FORMAT_TIME);
+
           GST_PUSH_LOCK (ogg);
           if (!ogg->pullmode && ogg->push_state == PUSH_LINEAR2) {
             /* if we are fast forwarding to the actual seek target,
@@ -974,14 +969,19 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
                 ", start_time %" GST_TIME_FORMAT,
                 GST_TIME_ARGS (ogg->push_seek_time_original_target),
                 GST_TIME_ARGS (start_time));
-            event =
-                gst_event_new_new_segment (FALSE, ogg->push_seek_rate,
-                GST_FORMAT_TIME, ogg->push_seek_time_original_target, -1,
-                ogg->push_seek_time_original_target);
+            segment.rate = ogg->push_seek_rate;
+            segment.start = ogg->push_seek_time_original_target;
+            segment.stop = -1;
+            segment.time = ogg->push_seek_time_original_target;
+            event = gst_event_new_segment (&segment);
             ogg->push_state = PUSH_PLAYING;
           } else {
-            event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
-                GST_FORMAT_TIME, start_time, chain->segment_stop, segment_time);
+            segment.rate = ogg->segment.rate;
+            segment.applied_rate = ogg->segment.applied_rate;
+            segment.start = start_time;
+            segment.stop = chain->segment_stop;
+            segment.time = segment_time;
+            event = gst_event_new_segment (&segment);
           }
           GST_PUSH_UNLOCK (ogg);
 
@@ -991,6 +991,7 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
         /* see if we have enough info to activate the chain, we have enough info
          * when all streams have a valid start time. */
         if (gst_ogg_demux_collect_chain_info (ogg, chain)) {
+          GstSegment segment;
 
           GST_DEBUG_OBJECT (ogg, "segment_start: %" GST_TIME_FORMAT,
               GST_TIME_ARGS (chain->segment_start));
@@ -1000,9 +1001,13 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
               GST_TIME_ARGS (chain->begin_time));
 
           /* create the newsegment event we are going to send out */
-          event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
-              GST_FORMAT_TIME, chain->segment_start, chain->segment_stop,
-              chain->begin_time);
+          gst_segment_init (&segment, GST_FORMAT_TIME);
+          segment.rate = ogg->segment.rate;
+          segment.applied_rate = ogg->segment.applied_rate;
+          segment.start = chain->segment_start;
+          segment.stop = chain->segment_stop;
+          segment.time = chain->begin_time;
+          event = gst_event_new_segment (&segment);
         }
       }
 
@@ -1694,8 +1699,7 @@ gst_ogg_chain_new_stream (GstOggChain * chain, guint32 serialno)
 
   ret = g_object_new (GST_TYPE_OGG_PAD, NULL);
   /* we own this one */
-  gst_object_ref (ret);
-  gst_object_sink (ret);
+  gst_object_ref_sink (ret);
 
   GST_PAD_DIRECTION (ret) = GST_PAD_SRC;
   gst_ogg_pad_mark_discont (ret);
@@ -1721,6 +1725,7 @@ gst_ogg_chain_new_stream (GstOggChain * chain, guint32 serialno)
       "created new ogg src %p for stream with serial %08x", ret, serialno);
 
   g_array_append_val (chain->streams, ret);
+  gst_pad_set_active (GST_PAD_CAST (ret), TRUE);
 
   return ret;
 
@@ -1800,29 +1805,24 @@ static GstStateChangeReturn gst_ogg_demux_change_state (GstElement * element,
 
 static void gst_ogg_print (GstOggDemux * demux);
 
-GST_BOILERPLATE (GstOggDemux, gst_ogg_demux, GstElement, GST_TYPE_ELEMENT);
+#define gst_ogg_demux_parent_class parent_class
+G_DEFINE_TYPE (GstOggDemux, gst_ogg_demux, GST_TYPE_ELEMENT);
 
 static void
-gst_ogg_demux_base_init (gpointer g_class)
+gst_ogg_demux_class_init (GstOggDemuxClass * klass)
 {
-  GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
-  gst_element_class_set_details_simple (element_class,
+  gst_element_class_set_details_simple (gstelement_class,
       "Ogg demuxer", "Codec/Demuxer",
       "demux ogg streams (info about ogg: http://xiph.org)",
       "Wim Taymans <wim@fluendo.com>");
 
-  gst_element_class_add_pad_template (element_class,
+  gst_element_class_add_pad_template (gstelement_class,
       gst_static_pad_template_get (&ogg_demux_sink_template_factory));
-  gst_element_class_add_pad_template (element_class,
+  gst_element_class_add_pad_template (gstelement_class,
       gst_static_pad_template_get (&ogg_demux_src_template_factory));
-}
-
-static void
-gst_ogg_demux_class_init (GstOggDemuxClass * klass)
-{
-  GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
   gstelement_class->change_state = gst_ogg_demux_change_state;
   gstelement_class->send_event = gst_ogg_demux_receive_event;
@@ -1831,7 +1831,7 @@ gst_ogg_demux_class_init (GstOggDemuxClass * klass)
 }
 
 static void
-gst_ogg_demux_init (GstOggDemux * ogg, GstOggDemuxClass * g_class)
+gst_ogg_demux_init (GstOggDemux * ogg)
 {
   /* create the sink pad */
   ogg->sinkpad =
@@ -1917,24 +1917,21 @@ gst_ogg_demux_sink_event (GstPad * pad, GstEvent * event)
         gst_ogg_demux_reset_streams (ogg);
       }
       break;
-    case GST_EVENT_NEWSEGMENT:
+    case GST_EVENT_SEGMENT:
       GST_DEBUG_OBJECT (ogg, "got a new segment event");
       {
-        gboolean update;
-        GstFormat format;
-        gdouble rate, arate;
-        gint64 start, stop, time;
-
-        gst_event_parse_new_segment_full (event, &update, &rate, &arate,
-            &format, &start, &stop, &time);
-        if (format == GST_FORMAT_BYTES) {
+        GstSegment segment;
+
+        gst_event_copy_segment (event, &segment);
+
+        if (segment.format == GST_FORMAT_BYTES) {
           GST_PUSH_LOCK (ogg);
-          ogg->push_byte_offset = start;
-          ogg->push_last_seek_offset = start;
+          ogg->push_byte_offset = segment.start;
+          ogg->push_last_seek_offset = segment.start;
           GST_PUSH_UNLOCK (ogg);
         } else {
           GST_WARNING_OBJECT (ogg, "unexpected segment format: %s",
-              gst_format_get_name (format));
+              gst_format_get_name (segment.format));
         }
       }
       gst_event_unref (event);
@@ -1982,15 +1979,12 @@ gst_ogg_demux_sink_event (GstPad * pad, GstEvent * event)
 static GstFlowReturn
 gst_ogg_demux_submit_buffer (GstOggDemux * ogg, GstBuffer * buffer)
 {
-  gint size;
-  guint8 *data;
+  gsize size;
   gchar *oggbuffer;
   GstFlowReturn ret = GST_FLOW_OK;
 
-  size = GST_BUFFER_SIZE (buffer);
-  data = GST_BUFFER_DATA (buffer);
-
-  GST_DEBUG_OBJECT (ogg, "submitting %u bytes", size);
+  size = gst_buffer_get_size (buffer);
+  GST_DEBUG_OBJECT (ogg, "submitting %" G_GSIZE_FORMAT " bytes", size);
   if (G_UNLIKELY (size == 0))
     goto done;
 
@@ -1998,7 +1992,8 @@ gst_ogg_demux_submit_buffer (GstOggDemux * ogg, GstBuffer * buffer)
   if (G_UNLIKELY (oggbuffer == NULL))
     goto no_buffer;
 
-  memcpy (oggbuffer, data, size);
+  gst_buffer_extract (buffer, 0, oggbuffer, size);
+
   if (G_UNLIKELY (ogg_sync_wrote (&ogg->sync, size) < 0))
     goto write_failed;
 
@@ -2023,8 +2018,8 @@ no_buffer:
   }
 write_failed:
   {
-    GST_ELEMENT_ERROR (ogg, STREAM, DECODE,
-        (NULL), ("failed to write %d bytes to the sync buffer", size));
+    GST_ELEMENT_ERROR (ogg, STREAM, DECODE, (NULL),
+        ("failed to write %" G_GSIZE_FORMAT " bytes to the sync buffer", size));
     ret = GST_FLOW_ERROR;
     goto done;
   }
@@ -2067,7 +2062,7 @@ gst_ogg_demux_get_data (GstOggDemux * ogg, gint64 end_offset)
   if (ret != GST_FLOW_OK)
     goto error;
 
-  ogg->read_offset += GST_BUFFER_SIZE (buffer);
+  ogg->read_offset += gst_buffer_get_size (buffer);
 
   ret = gst_ogg_demux_submit_buffer (ogg, buffer);
 
@@ -2311,7 +2306,7 @@ gst_ogg_demux_set_header_on_caps (GstOggDemux * ogg, GstCaps * caps,
     ogg_packet *op = headers->data;
     g_assert (op);
     buffer = gst_buffer_new_and_alloc (op->bytes);
-    memcpy (GST_BUFFER_DATA (buffer), op->packet, op->bytes);
+    gst_buffer_fill (buffer, 0, op->packet, op->bytes);
     GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_IN_CAPS);
     g_value_init (&value, GST_TYPE_BUFFER);
     gst_value_take_buffer (&value, buffer);
@@ -2384,7 +2379,8 @@ gst_ogg_demux_activate_chain (GstOggDemux * ogg, GstOggChain * chain,
     gst_ogg_pad_mark_discont (pad);
     pad->last_ret = GST_FLOW_OK;
 
-    if (pad->map.is_skeleton || pad->added || GST_PAD_CAPS (pad) == NULL)
+    if (pad->map.is_skeleton || pad->added
+        || !gst_pad_has_current_caps (GST_PAD_CAST (pad)))
       continue;
 
     GST_DEBUG_OBJECT (ogg, "adding pad %" GST_PTR_FORMAT, pad);
@@ -2648,7 +2644,7 @@ gst_ogg_demux_do_seek (GstOggDemux * ogg, GstSegment * segment,
   gint i, pending, len;
   gboolean first_parsed_page = TRUE;
 
-  position = segment->last_stop;
+  position = segment->position;
 
   /* first find the chain to search in */
   total = ogg->total_time;
@@ -2803,7 +2799,7 @@ done:
   if (keyframe) {
     if (segment->rate > 0.0)
       segment->time = keytarget;
-    segment->last_stop = keytarget - begintime;
+    segment->position = keytarget - begintime;
   }
 
   *rchain = chain;
@@ -2901,28 +2897,8 @@ gst_ogg_demux_perform_seek_pull (GstOggDemux * ogg, GstEvent * event)
    * forever. */
   GST_PAD_STREAM_LOCK (ogg->sinkpad);
 
-  if (ogg->segment_running && !flush) {
-    /* create the segment event to close the current segment */
-    if ((chain = ogg->current_chain)) {
-      GstEvent *newseg;
-      gint64 chain_start = 0;
-
-      if (chain->segment_start != GST_CLOCK_TIME_NONE)
-        chain_start = chain->segment_start;
-
-      newseg = gst_event_new_new_segment (TRUE, ogg->segment.rate,
-          GST_FORMAT_TIME, ogg->segment.start + chain_start,
-          ogg->segment.last_stop + chain_start, ogg->segment.time);
-      /* set the seqnum of the running segment */
-      gst_event_set_seqnum (newseg, ogg->seqnum);
-
-      /* send segment on old chain, FIXME, must be sent from streaming thread. */
-      gst_ogg_demux_send_event (ogg, newseg);
-    }
-  }
-
   if (event) {
-    gst_segment_set_seek (&ogg->segment, rate, format, flags,
+    gst_segment_do_seek (&ogg->segment, rate, format, flags,
         cur_type, cur, stop_type, stop, &update);
   }
 
@@ -2933,7 +2909,7 @@ gst_ogg_demux_perform_seek_pull (GstOggDemux * ogg, GstEvent * event)
   /* we need to stop flushing on the srcpad as we're going to use it
    * next. We can do this as we have the STREAM lock now. */
   if (flush) {
-    tevent = gst_event_new_flush_stop ();
+    tevent = gst_event_new_flush_stop (TRUE);
     gst_event_set_seqnum (tevent, seqnum);
     gst_pad_push_event (ogg->sinkpad, tevent);
   }
@@ -2969,11 +2945,12 @@ gst_ogg_demux_perform_seek_pull (GstOggDemux * ogg, GstEvent * event)
     GstEvent *event;
     gint64 stop;
     gint64 start;
-    gint64 last_stop, begin_time;
+    gint64 position, begin_time;
+    GstSegment segment;
 
     /* we have to send the flush to the old chain, not the new one */
     if (flush) {
-      tevent = gst_event_new_flush_stop ();
+      tevent = gst_event_new_flush_stop (TRUE);
       gst_event_set_seqnum (tevent, seqnum);
       gst_ogg_demux_send_event (ogg, tevent);
     }
@@ -3006,18 +2983,21 @@ gst_ogg_demux_perform_seek_pull (GstOggDemux * ogg, GstEvent * event)
       stop = MIN (stop, chain->segment_stop);
     }
 
-    last_stop = ogg->segment.last_stop;
+    position = ogg->segment.position;
     if (chain->segment_start != GST_CLOCK_TIME_NONE)
-      last_stop += chain->segment_start;
+      position += chain->segment_start;
 
-    /* create the segment event we are going to send out */
-    if (ogg->segment.rate >= 0.0)
-      event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
-          ogg->segment.format, last_stop, stop, ogg->segment.time);
-    else
-      event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
-          ogg->segment.format, start, last_stop, ogg->segment.time);
+    gst_segment_copy_into (&ogg->segment, &segment);
 
+    /* create the segment event we are going to send out */
+    if (ogg->segment.rate >= 0.0) {
+      segment.start = position;
+      segment.stop = stop;
+    } else {
+      segment.start = start;
+      segment.stop = position;
+    }
+    event = gst_event_new_segment (&segment);
     gst_event_set_seqnum (event, seqnum);
 
     if (chain != ogg->current_chain) {
@@ -3037,13 +3017,12 @@ gst_ogg_demux_perform_seek_pull (GstOggDemux * ogg, GstEvent * event)
       GstMessage *message;
 
       message = gst_message_new_segment_start (GST_OBJECT (ogg),
-          GST_FORMAT_TIME, ogg->segment.last_stop);
+          GST_FORMAT_TIME, ogg->segment.position);
       gst_message_set_seqnum (message, seqnum);
 
       gst_element_post_message (GST_ELEMENT (ogg), message);
     }
 
-    ogg->segment_running = TRUE;
     ogg->seqnum = seqnum;
     /* restart our task since it might have been stopped when we did the 
      * flush. */
@@ -3111,18 +3090,16 @@ gst_ogg_demux_check_duration_push (GstOggDemux * ogg, GstSeekFlags flags,
 
     GST_DEBUG_OBJECT (ogg, "Trying to find byte/time length");
     if ((peer = gst_pad_get_peer (ogg->sinkpad)) != NULL) {
-      GstFormat format = GST_FORMAT_BYTES;
       gint64 length;
       int res;
 
-      res = gst_pad_query_duration (peer, &format, &length);
+      res = gst_pad_query_duration (peer, GST_FORMAT_BYTES, &length);
       if (res && length > 0) {
         ogg->push_byte_length = length;
         GST_DEBUG_OBJECT (ogg,
             "File byte length %" G_GINT64_FORMAT, ogg->push_byte_length);
       }
-      format = GST_FORMAT_TIME;
-      res = gst_pad_query_duration (peer, &format, &length);
+      res = gst_pad_query_duration (peer, GST_FORMAT_TIME, &length);
       gst_object_unref (peer);
       if (res && length >= 0) {
         ogg->push_time_length = length;
@@ -3726,7 +3703,7 @@ gst_ogg_demux_collect_info (GstOggDemux * ogg)
 
     ogg->total_time += chain->total_time;
   }
-  gst_segment_set_duration (&ogg->segment, GST_FORMAT_TIME, ogg->total_time);
+  ogg->segment.duration = ogg->total_time;
 }
 
 /* find all the chains in the ogg file, this reads the first and
@@ -3738,7 +3715,6 @@ gst_ogg_demux_find_chains (GstOggDemux * ogg)
 {
   ogg_page og;
   GstPad *peer;
-  GstFormat format;
   gboolean res;
   guint32 serialno;
   GstOggChain *chain;
@@ -3749,8 +3725,7 @@ gst_ogg_demux_find_chains (GstOggDemux * ogg)
     goto no_peer;
 
   /* find length to read last page, we store this for later use. */
-  format = GST_FORMAT_BYTES;
-  res = gst_pad_query_duration (peer, &format, &ogg->length);
+  res = gst_pad_query_duration (peer, GST_FORMAT_BYTES, &ogg->length);
   gst_object_unref (peer);
   if (!res || ogg->length <= 0)
     goto no_length;
@@ -3849,13 +3824,17 @@ gst_ogg_demux_handle_page (GstOggDemux * ogg, ogg_page * page)
     if (chain) {
       GstEvent *event;
       gint64 start = 0;
+      GstSegment segment;
 
       if (chain->segment_start != GST_CLOCK_TIME_NONE)
         start = chain->segment_start;
 
       /* create the newsegment event we are going to send out */
-      event = gst_event_new_new_segment (FALSE, ogg->segment.rate,
-          GST_FORMAT_TIME, start, chain->segment_stop, chain->begin_time);
+      gst_segment_copy_into (&ogg->segment, &segment);
+      segment.start = start;
+      segment.stop = chain->segment_stop;
+      segment.time = chain->begin_time;
+      event = gst_event_new_segment (&segment);
       gst_event_set_seqnum (event, ogg->seqnum);
 
       GST_DEBUG_OBJECT (ogg,
@@ -3876,7 +3855,7 @@ gst_ogg_demux_handle_page (GstOggDemux * ogg, ogg_page * page)
       if (ogg->pullmode)
         goto unknown_chain;
 
-      current_time = ogg->segment.last_stop;
+      current_time = ogg->segment.position;
 
       /* time of new chain is current time */
       chain_time = current_time;
@@ -4086,7 +4065,7 @@ gst_ogg_demux_loop_forward (GstOggDemux * ogg)
     goto done;
   }
 
-  ogg->offset += GST_BUFFER_SIZE (buffer);
+  ogg->offset += gst_buffer_get_size (buffer);
 
   if (G_UNLIKELY (ogg->newsegment)) {
     gst_ogg_demux_send_event (ogg, ogg->newsegment);
@@ -4165,7 +4144,7 @@ gst_ogg_demux_sync_streams (GstOggDemux * ogg)
   guint i;
 
   chain = ogg->current_chain;
-  cur = ogg->segment.last_stop;
+  cur = ogg->segment.position;
   if (chain == NULL || cur == -1)
     return;
 
@@ -4175,18 +4154,24 @@ gst_ogg_demux_sync_streams (GstOggDemux * ogg)
     /* Theoretically, we should be doing this for all streams, but we're only
      * doing it for known-to-be-sparse streams at the moment in order not to
      * break things for wrongly-muxed streams (like we used to produce once) */
-    if (stream->map.is_sparse && stream->last_stop != GST_CLOCK_TIME_NONE) {
+    if (stream->map.is_sparse && stream->position != GST_CLOCK_TIME_NONE) {
 
       /* Does this stream lag? Random threshold of 2 seconds */
-      if (GST_CLOCK_DIFF (stream->last_stop, cur) > (2 * GST_SECOND)) {
+      if (GST_CLOCK_DIFF (stream->position, cur) > (2 * GST_SECOND)) {
         GST_DEBUG_OBJECT (stream, "synchronizing stream with others by "
             "advancing time from %" GST_TIME_FORMAT " to %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (stream->last_stop), GST_TIME_ARGS (cur));
-        stream->last_stop = cur;
+            GST_TIME_ARGS (stream->position), GST_TIME_ARGS (cur));
+
+        stream->position = cur;
+
+#if 0
+        ogg->segment.base += cur - stream->position;
         /* advance stream time (FIXME: is this right, esp. time_pos?) */
         gst_pad_push_event (GST_PAD_CAST (stream),
             gst_event_new_new_segment (TRUE, ogg->segment.rate,
-                GST_FORMAT_TIME, stream->last_stop, -1, stream->last_stop));
+                ogg->segment.applied_rate,
+                GST_FORMAT_TIME, stream->position, -1, stream->position));
+#endif
       }
     }
   }
@@ -4264,7 +4249,6 @@ pause:
     GstEvent *event = NULL;
 
     GST_LOG_OBJECT (ogg, "pausing task, reason %s", reason);
-    ogg->segment_running = FALSE;
     gst_pad_pause_task (ogg->sinkpad);
 
     if (ret == GST_FLOW_UNEXPECTED) {
@@ -4336,10 +4320,26 @@ gst_ogg_demux_clear_chains (GstOggDemux * ogg)
 static gboolean
 gst_ogg_demux_sink_activate (GstPad * sinkpad)
 {
-  if (gst_pad_check_pull_range (sinkpad)) {
-    GST_DEBUG_OBJECT (sinkpad, "activating pull");
-    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);
+
+  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);
   }
@@ -4398,7 +4398,6 @@ gst_ogg_demux_change_state (GstElement * element, GstStateChange transition)
       ogg_sync_reset (&ogg->sync);
       ogg->running = FALSE;
       ogg->bitrate = 0;
-      ogg->segment_running = FALSE;
       ogg->total_time = -1;
       GST_PUSH_LOCK (ogg);
       ogg->push_byte_offset = 0;
@@ -4416,7 +4415,7 @@ gst_ogg_demux_change_state (GstElement * element, GstStateChange transition)
       break;
   }
 
-  result = parent_class->change_state (element, transition);
+  result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
 
   switch (transition) {
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
@@ -4425,7 +4424,6 @@ gst_ogg_demux_change_state (GstElement * element, GstStateChange transition)
       gst_ogg_demux_clear_chains (ogg);
       GST_OBJECT_LOCK (ogg);
       ogg->running = FALSE;
-      ogg->segment_running = FALSE;
       GST_OBJECT_UNLOCK (ogg);
       break;
     case GST_STATE_CHANGE_READY_TO_NULL: