More segment updates, replace code in plugins with segment helper functions.
authorWim Taymans <wim.taymans@gmail.com>
Mon, 21 Nov 2005 17:09:45 +0000 (17:09 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Mon, 21 Nov 2005 17:09:45 +0000 (17:09 +0000)
Original commit message from CVS:
* check/gst/gstsegment.c: (GST_START_TEST):
* docs/design/part-TODO.txt:
* gst/base/gstbasesink.c: (gst_base_sink_handle_object),
(gst_base_sink_event), (gst_base_sink_do_sync),
(gst_base_sink_activate_pull), (gst_base_sink_get_position),
(gst_base_sink_query), (gst_base_sink_change_state):
* gst/base/gstbasesink.h:
* gst/base/gstbasesrc.c: (gst_base_src_init), (gst_base_src_query),
(gst_base_src_default_newsegment),
(gst_base_src_configure_segment), (gst_base_src_do_seek),
(gst_base_src_get_range), (gst_base_src_loop),
(gst_base_src_change_state):
* gst/base/gstbasesrc.h:
* gst/base/gstbasetransform.c:
(gst_base_transform_prepare_output_buf),
(gst_base_transform_event), (gst_base_transform_change_state):
* gst/base/gstbasetransform.h:
* gst/base/gstcollectpads.c: (gst_collect_pads_add_pad),
(gst_collect_pads_event):
* gst/base/gstcollectpads.h:
* gst/elements/gstfakesrc.c: (gst_fake_src_init),
(gst_fake_src_create):
* gst/elements/gstfakesrc.h:
* gst/elements/gstidentity.c: (gst_identity_transform_ip):
* gst/gstsegment.c: (gst_segment_init), (gst_segment_set_duration),
(gst_segment_set_last_stop), (gst_segment_set_seek),
(gst_segment_set_newsegment), (gst_segment_to_stream_time),
(gst_segment_to_running_time), (gst_segment_clip):
* gst/gstsegment.h:
More segment updates, replace code in plugins with segment
helper functions.

28 files changed:
ChangeLog
check/gst/gstsegment.c
docs/design/part-TODO.txt
gst/base/gstbasesink.c
gst/base/gstbasesink.h
gst/base/gstbasesrc.c
gst/base/gstbasesrc.h
gst/base/gstbasetransform.c
gst/base/gstbasetransform.h
gst/base/gstcollectpads.c
gst/base/gstcollectpads.h
gst/elements/gstfakesrc.c
gst/elements/gstfakesrc.h
gst/elements/gstidentity.c
gst/gstsegment.c
gst/gstsegment.h
libs/gst/base/gstbasesink.c
libs/gst/base/gstbasesink.h
libs/gst/base/gstbasesrc.c
libs/gst/base/gstbasesrc.h
libs/gst/base/gstbasetransform.c
libs/gst/base/gstbasetransform.h
libs/gst/base/gstcollectpads.c
libs/gst/base/gstcollectpads.h
plugins/elements/gstfakesrc.c
plugins/elements/gstfakesrc.h
plugins/elements/gstidentity.c
tests/check/gst/gstsegment.c

index 2f6031c..b21421d 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,37 @@
+2005-11-21  Wim Taymans  <wim@fluendo.com>
+
+       * check/gst/gstsegment.c: (GST_START_TEST):
+       * docs/design/part-TODO.txt:
+       * gst/base/gstbasesink.c: (gst_base_sink_handle_object),
+       (gst_base_sink_event), (gst_base_sink_do_sync),
+       (gst_base_sink_activate_pull), (gst_base_sink_get_position),
+       (gst_base_sink_query), (gst_base_sink_change_state):
+       * gst/base/gstbasesink.h:
+       * gst/base/gstbasesrc.c: (gst_base_src_init), (gst_base_src_query),
+       (gst_base_src_default_newsegment),
+       (gst_base_src_configure_segment), (gst_base_src_do_seek),
+       (gst_base_src_get_range), (gst_base_src_loop),
+       (gst_base_src_change_state):
+       * gst/base/gstbasesrc.h:
+       * gst/base/gstbasetransform.c:
+       (gst_base_transform_prepare_output_buf),
+       (gst_base_transform_event), (gst_base_transform_change_state):
+       * gst/base/gstbasetransform.h:
+       * gst/base/gstcollectpads.c: (gst_collect_pads_add_pad),
+       (gst_collect_pads_event):
+       * gst/base/gstcollectpads.h:
+       * gst/elements/gstfakesrc.c: (gst_fake_src_init),
+       (gst_fake_src_create):
+       * gst/elements/gstfakesrc.h:
+       * gst/elements/gstidentity.c: (gst_identity_transform_ip):
+       * gst/gstsegment.c: (gst_segment_init), (gst_segment_set_duration),
+       (gst_segment_set_last_stop), (gst_segment_set_seek),
+       (gst_segment_set_newsegment), (gst_segment_to_stream_time),
+       (gst_segment_to_running_time), (gst_segment_clip):
+       * gst/gstsegment.h:
+       More segment updates, replace code in plugins with segment
+       helper functions.
+
 2005-11-21  Jan Schmidt  <thaytan@mad.scientist.com>
 
        * gst/elements/gstfdsrc.c: (gst_fdsrc_uri_set_uri):
index b4e2f5b..e32715e 100644 (file)
@@ -27,13 +27,15 @@ GST_START_TEST (segment_seek_nosize)
   GstSegment segment;
   gboolean res;
   gint64 cstart, cstop;
+  gboolean update;
 
   gst_segment_init (&segment, GST_FORMAT_BYTES);
 
   /* configure segment to start 100 */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == -1);
 
@@ -41,7 +43,8 @@ GST_START_TEST (segment_seek_nosize)
    * size is unknown. */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100, &update);
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == -1);
 
@@ -99,7 +102,8 @@ GST_START_TEST (segment_seek_nosize)
   /* add 100 to start, set stop to 300 */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300, &update);
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 300);
 
@@ -107,7 +111,8 @@ GST_START_TEST (segment_seek_nosize)
    * nothing should be updated in the segment. */
   ASSERT_CRITICAL (gst_segment_set_seek (&segment, 1.0,
           GST_FORMAT_BYTES,
-          GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200));
+          GST_SEEK_FLAG_NONE,
+          GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200, &update));
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 300);
 
@@ -115,7 +120,8 @@ GST_START_TEST (segment_seek_nosize)
    * unknown. */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_END, -300, GST_SEEK_TYPE_END, -100);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_END, -300, GST_SEEK_TYPE_END, -100, &update);
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 300);
 
@@ -193,6 +199,7 @@ GST_START_TEST (segment_seek_size)
   GstSegment segment;
   gboolean res;
   gint64 cstart, cstop;
+  gboolean update;
 
   gst_segment_init (&segment, GST_FORMAT_BYTES);
   gst_segment_set_duration (&segment, GST_FORMAT_BYTES, 200);
@@ -200,7 +207,8 @@ GST_START_TEST (segment_seek_size)
   /* configure segment to start 100 */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == -1);
 
@@ -208,7 +216,8 @@ GST_START_TEST (segment_seek_size)
    * since we did not set it before. */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100, &update);
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == -1);
 
@@ -273,7 +282,8 @@ GST_START_TEST (segment_seek_size)
   /* add 100 to start, set stop to 300, stop clips to 200 */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300, &update);
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 200);
 
@@ -281,14 +291,16 @@ GST_START_TEST (segment_seek_size)
    * to duration */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200, &update);
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 200);
 
   /* seek relative to end */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_END, -100, GST_SEEK_TYPE_END, -20);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_END, -100, GST_SEEK_TYPE_END, -20, &update);
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == 180);
 
index 548f874..a8da5db 100644 (file)
@@ -15,8 +15,6 @@ API/ABI
 
 - unblocking while seeking. gst_element_flush_pads (GstElement, gboolean);
 
-- make GstCapsFlags instead of the #define for GST_CAPS_FLAGS_ANY.
-
 - query POSITION/DURATION return accuracy. Just a flag or accuracy percentage.
 
 - add some sort of time/frame stepping functionality, either with a flag on the seek
@@ -26,10 +24,6 @@ API/ABI
   N frames/time, sending more complicated queries upstream which can ideally handle
   those cases more efficiently too.
 
-- GstClockFlags should use the gstobject flags field instead of inventing its own.
-
-- Add gstsegment.[ch].
-
 
 IMPLEMENTATION
 --------------
index f0c948a..cd5477e 100644 (file)
@@ -579,81 +579,28 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
         gboolean update;
         gdouble rate;
         GstFormat format;
-        gint64 segment_start;
-        gint64 segment_stop;
-        gint64 segment_time;
-        GstClockTime duration;
+        gint64 start;
+        gint64 stop;
+        gint64 time;
 
         /* the newsegment event is needed to bring the buffer timestamps to the
          * stream time and to drop samples outside of the playback segment. */
         gst_event_parse_newsegment (event, &update, &rate, &format,
-            &segment_start, &segment_stop, &segment_time);
+            &start, &stop, &time);
 
         basesink->have_newsegment = TRUE;
 
-        /* any other format with 0 also gives time 0, the other values are
-         * invalid as time though. */
-        if (format != GST_FORMAT_TIME && segment_start == 0) {
-          GST_DEBUG_OBJECT (basesink,
-              "non-time newsegment with start 0, coaxing into FORMAT_TIME");
-          format = GST_FORMAT_TIME;
-          if (segment_stop != 0)
-            segment_stop = -1;
-          if (segment_time != 0)
-            segment_time = -1;
-        }
-
-        if (format != GST_FORMAT_TIME) {
-          GST_DEBUG_OBJECT (basesink,
-              "received non time %d NEW_SEGMENT %" G_GINT64_FORMAT
-              " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT,
-              format, segment_start, segment_stop, segment_time);
-
-          /* this means this sink will not be able to clip or drop samples
-           * and timestamps have to start from 0. */
-          basesink->segment_start = -1;
-          basesink->segment_stop = -1;
-          basesink->segment_time = -1;
-          goto done_newsegment;
-        }
-        /* check if we really have a new segment or the previous one is
-         * closed */
-        if (!update) {
-          /* the new segment has to be aligned with the old segment.
-           * We first update the accumulated time of the previous
-           * segment. the accumulated time is used when syncing to the
-           * clock. A flush event sets the accumulated time back to 0
-           */
-          if (GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) {
-            duration = basesink->segment_stop - basesink->segment_start;
-          } else if (GST_CLOCK_TIME_IS_VALID (basesink->current_end)) {
-            /* else use last seen timestamp as segment stop */
-            duration = basesink->current_end - basesink->segment_start;
-          } else {
-            duration = 0;
-          }
-        } else {
-          duration = segment_start - basesink->segment_start;
-        }
-
-        /* use previous rate to calculate duration */
-        basesink->segment_accum += gst_gdouble_to_guint64 (
-            (gst_guint64_to_gdouble (duration) / ABS (basesink->segment_rate)));
-        /* then update the current segment */
-        basesink->segment_rate = rate;
-        basesink->segment_start = segment_start;
-        basesink->segment_stop = segment_stop;
-        basesink->segment_time = segment_time;
+        gst_segment_set_newsegment (&basesink->segment, update, rate, format,
+            start, stop, time);
 
         GST_DEBUG_OBJECT (basesink,
             "received NEWSEGMENT %" GST_TIME_FORMAT " -- %"
             GST_TIME_FORMAT ", time %" GST_TIME_FORMAT ", accum %"
             GST_TIME_FORMAT,
-            GST_TIME_ARGS (basesink->segment_start),
-            GST_TIME_ARGS (basesink->segment_stop),
-            GST_TIME_ARGS (basesink->segment_time),
-            GST_TIME_ARGS (basesink->segment_accum));
-      done_newsegment:
+            GST_TIME_ARGS (basesink->segment.start),
+            GST_TIME_ARGS (basesink->segment.stop),
+            GST_TIME_ARGS (basesink->segment.time),
+            GST_TIME_ARGS (basesink->segment.accum));
         break;
       }
       default:
@@ -669,8 +616,8 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
           ("Received buffer without a new-segment. Cannot sync to clock."));
       basesink->have_newsegment = TRUE;
       /* this means this sink will not be able to sync to the clock */
-      basesink->segment_start = -1;
-      basesink->segment_stop = -1;
+      basesink->segment.start = -1;
+      basesink->segment.stop = -1;
     }
 
     /* check if the buffer needs to be dropped */
@@ -685,28 +632,10 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
           ", end: %" GST_TIME_FORMAT, GST_TIME_ARGS (start),
           GST_TIME_ARGS (end));
 
-      /* need to drop if the timestamp is not between segment_start and
-       * segment_stop. we check if the complete sample is outside of the
-       * range since the sink might be able to clip the sample. */
-      if (GST_CLOCK_TIME_IS_VALID (end) &&
-          GST_CLOCK_TIME_IS_VALID (basesink->segment_start)) {
-        if (end <= basesink->segment_start) {
-          GST_DEBUG_OBJECT (basesink,
-              "buffer end %" GST_TIME_FORMAT " <= segment start %"
-              GST_TIME_FORMAT ", dropping buffer", GST_TIME_ARGS (end),
-              GST_TIME_ARGS (basesink->segment_start));
+      if (GST_CLOCK_TIME_IS_VALID (start)) {
+        if (!gst_segment_clip (&basesink->segment, GST_FORMAT_TIME,
+                (gint64) start, (gint64) end, NULL, NULL))
           goto dropping;
-        }
-      }
-      if (GST_CLOCK_TIME_IS_VALID (start) &&
-          GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) {
-        if (basesink->segment_stop <= start) {
-          GST_DEBUG_OBJECT (basesink,
-              "buffer start %" GST_TIME_FORMAT " >= segment stop %"
-              GST_TIME_FORMAT ", dropping buffer", GST_TIME_ARGS (start),
-              GST_TIME_ARGS (basesink->segment_stop));
-          goto dropping;
-        }
       }
     }
     basesink->preroll_queued++;
@@ -917,13 +846,7 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
       basesink->flushing = FALSE;
       GST_OBJECT_UNLOCK (basesink);
       /* we need new segment info after the flush. */
-      basesink->segment_start = -1;
-      basesink->segment_stop = -1;
-      basesink->current_start = -1;
-      basesink->current_end = -1;
-      GST_DEBUG_OBJECT (basesink, "reset accum %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (basesink->segment_accum));
-      basesink->segment_accum = 0;
+      gst_segment_init (&basesink->segment, GST_FORMAT_TIME);
       GST_STREAM_UNLOCK (pad);
 
       GST_DEBUG_OBJECT (basesink, "event unref %p %p", basesink, event);
@@ -1004,9 +927,8 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
 {
   GstClockReturn result = GST_CLOCK_OK;
   GstClockTime start, end;
-  GstClockTimeDiff stream_start, stream_end;
+  gint64 cstart, cend;
   GstBaseSinkClass *bclass;
-  gboolean start_valid, end_valid;
 
   bclass = GST_BASE_SINK_GET_CLASS (basesink);
 
@@ -1014,61 +936,27 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
   if (bclass->get_times)
     bclass->get_times (basesink, buffer, &start, &end);
 
-  start_valid = GST_CLOCK_TIME_IS_VALID (start);
-  end_valid = GST_CLOCK_TIME_IS_VALID (end);
-
   GST_DEBUG_OBJECT (basesink, "got times start: %" GST_TIME_FORMAT
       ", end: %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (end));
 
   /* if we don't have a timestamp, we don't sync */
-  if (!start_valid) {
+  if (!GST_CLOCK_TIME_IS_VALID (start)) {
     GST_DEBUG_OBJECT (basesink, "start not valid");
     goto done;
   }
 
   /* save last times seen. */
-  basesink->current_start = start;
-  if (end_valid)
-    basesink->current_end = end;
+  if (GST_CLOCK_TIME_IS_VALID (end))
+    gst_segment_set_last_stop (&basesink->segment, GST_FORMAT_TIME,
+        (gint64) end);
   else
-    basesink->current_end = start;
+    gst_segment_set_last_stop (&basesink->segment, GST_FORMAT_TIME,
+        (gint64) start);
 
-  if (GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) {
-    /* check if not outside of the segment range, start is
-     * always valid here. */
-    if (start > basesink->segment_stop)
-      goto out_of_segment;
-  }
-
-  /* bring timestamp to stream time using last segment offset. */
-  if (GST_CLOCK_TIME_IS_VALID (basesink->segment_start)) {
-    /* check if not outside of the segment range */
-    if (end_valid && end < basesink->segment_start)
-      goto out_of_segment;
-
-    stream_start = (gint64) start - basesink->segment_start;
-    stream_end = (gint64) end - basesink->segment_start;
-
-    if (stream_start < 0) {
-      GST_DEBUG_OBJECT (basesink, "stream_start negative, invalid");
-      goto done;
-    }
-  } else {
-    stream_start = (gint64) start;
-    stream_end = (gint64) end;
-  }
-
-
-  /* correct for rate */
-  if (basesink->segment_rate != 0.0) {
-    stream_start /= ABS (basesink->segment_rate);
-    if (end_valid)
-      stream_end /= ABS (basesink->segment_rate);
-  }
-
-  stream_start += basesink->segment_accum;
-  if (end_valid)
-    stream_end += basesink->segment_accum;
+  /* clip */
+  if (!gst_segment_clip (&basesink->segment, GST_FORMAT_TIME,
+          (gint64) start, (gint64) end, &cstart, &cend))
+    goto out_of_segment;
 
   if (!basesink->sync) {
     GST_DEBUG_OBJECT (basesink, "no need to sync");
@@ -1078,6 +966,13 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
   /* now do clocking */
   if (basesink->clock) {
     GstClockTime base_time;
+    GstClockTimeDiff stream_start, stream_end;
+
+    stream_start =
+        gst_segment_to_running_time (&basesink->segment, GST_FORMAT_TIME,
+        cstart);
+    stream_end =
+        gst_segment_to_running_time (&basesink->segment, GST_FORMAT_TIME, cend);
 
     GST_OBJECT_LOCK (basesink);
 
@@ -1090,7 +985,7 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
 
     /* also save end_time of this buffer so that we can wait
      * to signal EOS */
-    if (end_valid)
+    if (GST_CLOCK_TIME_IS_VALID (stream_end))
       basesink->end_time = stream_end + base_time;
     else
       basesink->end_time = GST_CLOCK_TIME_NONE;
@@ -1386,7 +1281,7 @@ gst_base_sink_activate_pull (GstPad * pad, gboolean active)
       } else {
         if (gst_pad_activate_pull (peer, TRUE)) {
           basesink->have_newsegment = TRUE;
-          basesink->segment_start = basesink->segment_stop = 0;
+          gst_segment_init (&basesink->segment, GST_FORMAT_TIME);
 
           /* set the pad mode before starting the task so that it's in the
              correct state for the new thread... */
@@ -1467,7 +1362,7 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
       GST_OBJECT_LOCK (basesink);
       if ((clock = GST_ELEMENT_CLOCK (basesink))) {
         GstClockTime now;
-        gint64 segment_time;
+        gint64 time;
 
         gst_object_ref (clock);
         GST_OBJECT_UNLOCK (basesink);
@@ -1475,18 +1370,18 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
         now = gst_clock_get_time (clock);
 
         GST_OBJECT_LOCK (basesink);
-        if (GST_CLOCK_TIME_IS_VALID (basesink->segment_time))
-          segment_time = basesink->segment_time;
+        if (GST_CLOCK_TIME_IS_VALID (basesink->segment.time))
+          time = basesink->segment.time;
         else
-          segment_time = 0;
+          time = 0;
 
         *cur = now - GST_ELEMENT_CAST (basesink)->base_time -
-            basesink->segment_accum + segment_time;
+            basesink->segment.accum + time;
 
         GST_DEBUG_OBJECT (basesink,
             "now %" GST_TIME_FORMAT " + segment_time %" GST_TIME_FORMAT " = %"
             GST_TIME_FORMAT, GST_TIME_ARGS (now),
-            GST_TIME_ARGS (segment_time), GST_TIME_ARGS (*cur));
+            GST_TIME_ARGS (time), GST_TIME_ARGS (*cur));
 
         gst_object_unref (clock);
 
@@ -1547,8 +1442,8 @@ gst_base_sink_query (GstElement * element, GstQuery * query)
     case GST_QUERY_SEGMENT:
     {
       /* FIXME, bring start/stop to stream time */
-      gst_query_set_segment (query, basesink->segment_rate,
-          GST_FORMAT_TIME, basesink->segment_start, basesink->segment_stop);
+      gst_query_set_segment (query, basesink->segment.rate,
+          GST_FORMAT_TIME, basesink->segment.start, basesink->segment.stop);
       break;
     }
     case GST_QUERY_SEEKING:
@@ -1585,15 +1480,8 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
       GST_DEBUG_OBJECT (basesink, "READY to PAUSED, need preroll to FALSE");
       basesink->need_preroll = TRUE;
       GST_PREROLL_UNLOCK (basesink->sinkpad);
+      gst_segment_init (&basesink->segment, GST_FORMAT_TIME);
       basesink->have_newsegment = FALSE;
-      basesink->segment_rate = 1.0;
-      basesink->segment_start = 0;
-      basesink->segment_stop = -1;
-      basesink->segment_time = 0;
-      basesink->current_start = -1;
-      basesink->current_duration = -1;
-      basesink->current_end = -1;
-      basesink->segment_accum = 0;
       ret = GST_STATE_CHANGE_ASYNC;
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
index f3fb83a..bb87cb5 100644 (file)
@@ -80,15 +80,7 @@ struct _GstBaseSink {
 
   /*< protected >*/ /* with STREAM_LOCK */
   gboolean      have_newsegment;
-  gdouble       segment_rate;
-  gint64        segment_start;
-  gint64        segment_stop;
-  gint64        segment_time;
-  gint64        segment_accum;
-
-  gint64        current_start;
-  gint64        current_duration;
-  gint64        current_end;
+  GstSegment     segment;
 
   /*< private >*/ /* with LOCK */
   GstClock     *clock;
index 9080623..d57e6c3 100644 (file)
@@ -229,8 +229,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
 
   basesrc->blocksize = DEFAULT_BLOCKSIZE;
   basesrc->clock_id = NULL;
-  basesrc->segment_start = 0;
-  basesrc->segment_end = -1;
+  gst_segment_init (&basesrc->segment, GST_FORMAT_BYTES);
 
   GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
 
@@ -411,9 +410,9 @@ gst_base_src_query (GstPad * pad, GstQuery * query)
     {
       gint64 start, stop;
 
-      start = src->segment_start;
+      start = src->segment.start;
       /* no end segment configured, current size then */
-      if ((stop = src->segment_end) == -1)
+      if ((stop = src->segment.stop) == -1)
         stop = src->size;
 
       /* FIXME, we can't report our rate as we did not store it, d'oh!.
@@ -448,11 +447,11 @@ gst_base_src_default_newsegment (GstBaseSrc * src)
   GstEvent *event;
 
   GST_DEBUG_OBJECT (src, "Sending newsegment from %" G_GINT64_FORMAT
-      " to %" G_GINT64_FORMAT, src->segment_start, src->segment_end);
+      " to %" G_GINT64_FORMAT, src->segment.start, src->segment.stop);
 
   event = gst_event_new_newsegment (FALSE, 1.0,
-      GST_FORMAT_BYTES, src->segment_start, src->segment_end,
-      src->segment_start);
+      GST_FORMAT_BYTES, src->segment.start, src->segment.stop,
+      src->segment.start);
 
   return gst_pad_push_event (src->srcpad, event);
 }
@@ -471,7 +470,7 @@ gst_base_src_newsegment (GstBaseSrc * src)
   return result;
 }
 
-/* based on the event parameters configure the segment_start/stop
+/* based on the event parameters configure the segment.start/stop
  * times. Called with STREAM_LOCK.
  */
 static gboolean
@@ -482,84 +481,20 @@ gst_base_src_configure_segment (GstBaseSrc * src, GstEvent * event)
   GstSeekFlags flags;
   GstSeekType cur_type, stop_type;
   gint64 cur, stop;
-  gboolean update_stop, update_start;
+  gboolean update;
 
   gst_event_parse_seek (event, &rate, &format, &flags,
       &cur_type, &cur, &stop_type, &stop);
 
-  /* parse the loop flag */
-  /* FIXME, need to store other flags and rate too */
-  src->segment_loop = (flags & GST_SEEK_FLAG_SEGMENT) != 0;
-
-  /* assume we'll update both start and stop values */
-  update_start = TRUE;
-  update_stop = TRUE;
-
-  /* perform the seek, segment_start is never invalid */
-  switch (cur_type) {
-    case GST_SEEK_TYPE_NONE:
-      /* no update to segment */
-      cur = src->segment_start;
-      update_start = FALSE;
-      break;
-    case GST_SEEK_TYPE_SET:
-      /* cur holds desired position */
-      break;
-    case GST_SEEK_TYPE_CUR:
-      /* add cur to currently configure segment */
-      cur = src->segment_start + cur;
-      break;
-    case GST_SEEK_TYPE_END:
-      /* add cur to total length */
-      cur = src->size + cur;
-      break;
-  }
-  /* bring in sane range */
-  if (src->size != -1)
-    cur = CLAMP (cur, 0, src->size);
-  else
-    cur = MAX (cur, 0);
-
-  /* segment_end can be -1 if we have not configured a stop. */
-  switch (stop_type) {
-    case GST_SEEK_TYPE_NONE:
-      stop = src->segment_end;
-      update_stop = FALSE;
-      break;
-    case GST_SEEK_TYPE_SET:
-      /* stop folds required value */
-      break;
-    case GST_SEEK_TYPE_CUR:
-      if (src->segment_end != -1)
-        stop = src->segment_end + stop;
-      else
-        stop = -1;
-      break;
-    case GST_SEEK_TYPE_END:
-      if (src->size != -1)
-        stop = src->size + stop;
-      else
-        stop = -1;
-      break;
-  }
-
-  /* if we have a valid stop time, make sure it is clipped */
-  if (stop != -1) {
-    if (src->size != -1)
-      stop = CLAMP (stop, 0, src->size);
-    else
-      stop = MAX (stop, 0);
-  }
-
-  src->segment_start = cur;
-  src->segment_end = stop;
+  gst_segment_set_seek (&src->segment, rate, format, flags,
+      cur_type, cur, stop_type, stop, &update);
 
   /* update our offset if it was updated */
-  if (update_start)
+  if (update)
     src->offset = cur;
 
   GST_DEBUG_OBJECT (src, "segment configured from %" G_GINT64_FORMAT
-      " to %" G_GINT64_FORMAT, src->segment_start, src->segment_end);
+      " to %" G_GINT64_FORMAT, src->segment.start, src->segment.stop);
 
   return TRUE;
 }
@@ -567,9 +502,9 @@ gst_base_src_configure_segment (GstBaseSrc * src, GstEvent * event)
 /* this code implements the seeking. It is a good example
  * handling all cases (modulo the FIXMEs).
  *
- * A seek updates the currently configured segment_start
- * and segment_stop values based on the SEEK_TYPE. If the
- * segment_start value is updated, a seek to this new position
+ * A seek updates the currently configured segment.start
+ * and segment.stop values based on the SEEK_TYPE. If the
+ * segment.start value is updated, a seek to this new position
  * should be performed.
  *
  * The seek can only be executed when we are not currently
@@ -592,13 +527,13 @@ gst_base_src_configure_segment (GstBaseSrc * src, GstEvent * event)
  * can continue the seek. A non-flushing seek is normally done in a 
  * running pipeline to perform seamless playback.
  *
- * After updating the segment_start/stop values, we prepare for
+ * After updating the segment.start/stop values, we prepare for
  * streaming again. We push out a FLUSH_STOP to make the peer pad
  * accept data again and we start our task again.
  *
  * A segment seek posts a message on the bus saying that the playback
  * of the segment started. We store the segment flag internally because
- * when we reach the segment_stop we have to post a segment_done
+ * when we reach the segment.stop we have to post a segment.done
  * instead of EOS when doing a segment seek.
  */
 static gboolean
@@ -648,11 +583,11 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
    * thread. We could opt to send it here too. */
   src->need_newsegment = TRUE;
 
-  if (src->segment_loop) {
+  if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
     /* FIXME subclasses should be able to provide other formats */
     gst_element_post_message (GST_ELEMENT (src),
         gst_message_new_segment_start (GST_OBJECT (src), GST_FORMAT_BYTES,
-            src->segment_start));
+            src->segment.start));
   }
 
   /* and restart the task in case it got paused explicitely or by
@@ -906,16 +841,16 @@ gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
     goto no_function;
 
   /* the max amount of bytes to read is the total size or
-   * up to the segment_end if present. */
-  if (src->segment_end != -1)
-    maxsize = MIN (src->size, src->segment_end);
+   * up to the segment.stop if present. */
+  if (src->segment.stop != -1)
+    maxsize = MIN (src->size, src->segment.stop);
   else
     maxsize = src->size;
 
   GST_DEBUG_OBJECT (src,
       "reading offset %" G_GUINT64_FORMAT ", length %u, size %" G_GINT64_FORMAT
-      ", segment_end %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset,
-      length, src->size, src->segment_end, maxsize);
+      ", segment.stop %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset,
+      length, src->size, src->segment.stop, maxsize);
 
   /* check size */
   if (maxsize != -1) {
@@ -927,8 +862,8 @@ gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
       if (bclass->get_size)
         bclass->get_size (src, &src->size);
 
-      if (src->segment_end != -1)
-        maxsize = MIN (src->size, src->segment_end);
+      if (src->segment.stop != -1)
+        maxsize = MIN (src->size, src->segment.stop);
       else
         maxsize = src->size;
 
@@ -1072,11 +1007,11 @@ eos:
   {
     GST_DEBUG_OBJECT (src, "going to EOS, getrange returned UNEXPECTED");
     gst_pad_pause_task (pad);
-    if (src->segment_loop) {
+    if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
       /* FIXME, subclass might want to use another format */
       gst_element_post_message (GST_ELEMENT (src),
           gst_message_new_segment_done (GST_OBJECT (src),
-              GST_FORMAT_BYTES, src->segment_end));
+              GST_FORMAT_BYTES, src->segment.stop));
     } else {
       gst_pad_push_event (pad, gst_event_new_eos ());
     }
@@ -1493,9 +1428,7 @@ gst_base_src_change_state (GstElement * element, GstStateChange transition)
       /* we always run from start to end when in READY, after putting
        * the element to READY a seek can be done on the element to
        * configure the segment when going to PAUSED. */
-      basesrc->segment_loop = FALSE;
-      basesrc->segment_start = 0;
-      basesrc->segment_end = -1;
+      gst_segment_init (&basesrc->segment, GST_FORMAT_BYTES);
       basesrc->offset = 0;
       break;
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
@@ -1510,9 +1443,7 @@ gst_base_src_change_state (GstElement * element, GstStateChange transition)
       if (!gst_base_src_stop (basesrc))
         goto error_stop;
       /* we always run from start to end when in READY */
-      basesrc->segment_loop = FALSE;
-      basesrc->segment_start = 0;
-      basesrc->segment_end = -1;
+      gst_segment_init (&basesrc->segment, GST_FORMAT_BYTES);
       basesrc->offset = 0;
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
index f62f1c0..1d788a5 100644 (file)
@@ -84,9 +84,7 @@ struct _GstBaseSrc {
   GstClockTime   end_time;
 
   /* MT-protected (with STREAM_LOCK) */
-  gint64        segment_start; /* start and end positions for seeking */
-  gint64        segment_end;
-  gboolean      segment_loop;
+  GstSegment     segment;
   gboolean      need_newsegment;
 
   guint64       offset;        /* current offset in the resource */
index ba50418..e856c51 100644 (file)
@@ -854,6 +854,7 @@ gst_base_transform_prepare_output_buf (GstBaseTransform * trans,
     if (G_UNLIKELY (!gst_caps_is_equal (out_caps, GST_BUFFER_CAPS (*out_buf)))) {
       /* FIXME, it is possible we can reconfigure the transform with new caps at this
        * point but for now we just create a buffer ourselves */
+      gst_buffer_unref (*out_buf);
       *out_buf = gst_buffer_new_and_alloc (out_size);
       gst_buffer_set_caps (*out_buf, out_caps);
     }
@@ -1056,13 +1057,7 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
       GST_STREAM_LOCK (pad);
       unlock = TRUE;
       /* we need new segment info after the flush. */
-      trans->segment_rate = 1.0;
-      trans->segment_start = -1;
-      trans->segment_stop = -1;
-      trans->segment_base = -1;
-      GST_DEBUG_OBJECT (trans, "reset accum %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (trans->segment_accum));
-      trans->segment_accum = 0;
+      gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);
       break;
     case GST_EVENT_EOS:
       GST_STREAM_LOCK (pad);
@@ -1076,7 +1071,7 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
     {
       GstFormat format;
       gdouble rate;
-      gint64 start, stop, time, duration;
+      gint64 start, stop, time;
       gboolean update;
 
       GST_STREAM_LOCK (pad);
@@ -1084,63 +1079,25 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
       gst_event_parse_newsegment (event, &update, &rate, &format, &start, &stop,
           &time);
 
-      /* any other format with 0 also gives time 0, the other values are
-       * invalid as time though. */
-      if (format != GST_FORMAT_TIME) {
-        GST_DEBUG_OBJECT (trans,
-            "non-time newsegment with start 0, coaxing into FORMAT_TIME");
-        format = GST_FORMAT_TIME;
-        if (start != 0)
-          start = -1;
-        if (stop != 0)
-          stop = -1;
-        if (time != 0)
-          time = -1;
-      }
-
-      /* check if we really have a new segment or the previous one is
-       * closed */
-      if (!update) {
-        /* the new segment has to be aligned with the old segment.
-         * We first update the accumulated time of the previous
-         * segment. the accumulated time is used when syncing to the
-         * clock. A flush event sets the accumulated time back to 0
-         */
-        if (GST_CLOCK_TIME_IS_VALID (trans->segment_stop)) {
-          duration = trans->segment_stop - trans->segment_start;
-        } else {
-          duration = 0;
-        }
-      } else {
-        if (GST_CLOCK_TIME_IS_VALID (start))
-          duration = start - trans->segment_start;
-        else
-          duration = 0;
-      }
+      gst_segment_set_newsegment (&trans->segment, update, rate, format, start,
+          stop, time);
 
       trans->have_newsegment = TRUE;
 
-      trans->segment_accum += gst_gdouble_to_guint64 (
-          (gst_guint64_to_gdouble (duration) / ABS (trans->segment_rate)));;
-      trans->segment_rate = rate;
-      trans->segment_start = start;
-      trans->segment_stop = stop;
-      trans->segment_base = time;
-
       if (format == GST_FORMAT_TIME) {
         GST_DEBUG_OBJECT (trans, "received NEW_SEGMENT %" GST_TIME_FORMAT
             " -- %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT
             ", accum %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (trans->segment_start),
-            GST_TIME_ARGS (trans->segment_stop),
-            GST_TIME_ARGS (trans->segment_base),
-            GST_TIME_ARGS (trans->segment_accum));
+            GST_TIME_ARGS (trans->segment.start),
+            GST_TIME_ARGS (trans->segment.stop),
+            GST_TIME_ARGS (trans->segment.time),
+            GST_TIME_ARGS (trans->segment.accum));
       } else {
         GST_DEBUG_OBJECT (trans, "received NEW_SEGMENT %" G_GINT64_FORMAT
             " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT
             ", accum %" G_GINT64_FORMAT,
-            trans->segment_start, trans->segment_stop,
-            trans->segment_base, trans->segment_accum);
+            trans->segment.start, trans->segment.stop,
+            trans->segment.time, trans->segment.accum);
       }
       break;
     }
@@ -1432,11 +1389,7 @@ gst_base_transform_change_state (GstElement * element,
       GST_DEBUG_OBJECT (trans, "have_same_caps %d", trans->have_same_caps);
       trans->negotiated = FALSE;
       trans->have_newsegment = FALSE;
-      trans->segment_rate = 1.0;
-      trans->segment_start = 0;
-      trans->segment_stop = -1;
-      trans->segment_base = 0;
-      trans->segment_accum = 0;
+      gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);
       GST_OBJECT_UNLOCK (trans);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
index 77a4268..fdd4ac1 100644 (file)
@@ -65,6 +65,7 @@ struct _GstBaseTransform {
   guint                 cache_caps1_size;
   GstCaps      *cache_caps2;
   guint                 cache_caps2_size;
+  gboolean      have_same_caps;
 
   gboolean      delay_configure;
   gboolean      pending_configure;
@@ -73,22 +74,12 @@ struct _GstBaseTransform {
   gboolean       have_newsegment;
 
   /* MT-protected (with STREAM_LOCK) */
-  gdouble        segment_rate;
-  gint64         segment_start;
-  gint64         segment_stop;
-  gint64         segment_base;
-
-  union {
-    /* FIXME: When adjusting the padding, move this to a nice place in the structure */
-    /* Set if caps on each pad are equal */
-    struct {
-      gboolean  have_same_caps;
-      GMutex   *transform_lock;
-      gint64     segment_accum;
-    };
-    /*< private >*/
-    gpointer       _gst_reserved[GST_PADDING-1+1];
-  };
+  GstSegment     segment;
+
+  GMutex       *transform_lock;
+
+  /*< private >*/
+  gpointer       _gst_reserved[GST_PADDING];
 };
 
 /**
@@ -165,15 +156,16 @@ struct _GstBaseTransformClass {
   gpointer       _gst_reserved[GST_PADDING - 2];
 };
 
-void           gst_base_transform_set_passthrough (GstBaseTransform *trans,
-                   gboolean passthrough);
-gboolean       gst_base_transform_is_passthrough (GstBaseTransform *trans);
+GType           gst_base_transform_get_type         (void);
+
+void           gst_base_transform_set_passthrough  (GstBaseTransform *trans,
+                                                    gboolean passthrough);
+gboolean       gst_base_transform_is_passthrough   (GstBaseTransform *trans);
 
-void           gst_base_transform_set_in_place (GstBaseTransform *trans,
-                   gboolean in_place);
-gboolean       gst_base_transform_is_in_place (GstBaseTransform *trans);
+void           gst_base_transform_set_in_place     (GstBaseTransform *trans,
+                                                    gboolean in_place);
+gboolean       gst_base_transform_is_in_place      (GstBaseTransform *trans);
 
-GType gst_base_transform_get_type (void);
 
 G_END_DECLS
 
index de08df4..d3a48fc 100644 (file)
@@ -196,6 +196,7 @@ gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size)
   data->collect = pads;
   data->pad = pad;
   data->buffer = NULL;
+  gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED);
 
   GST_OBJECT_LOCK (pads);
   pads->data = g_slist_append (pads->data, data);
@@ -599,20 +600,16 @@ gst_collect_pads_event (GstPad * pad, GstEvent * event)
     }
     case GST_EVENT_NEWSEGMENT:
     {
-      gint64 segment_start, segment_stop, stream_time;
-      gdouble segment_rate;
+      gint64 start, stop, time;
+      gdouble rate;
       GstFormat format;
       gboolean update;
 
-      gst_event_parse_newsegment (event, &update, &segment_rate, &format,
-          &segment_start, &segment_stop, &stream_time);
-
-      if (format == GST_FORMAT_TIME) {
-        data->segment_start = segment_start;
-        data->segment_stop = segment_stop;
-        data->stream_time = stream_time;
-      }
+      gst_event_parse_newsegment (event, &update, &rate, &format,
+          &start, &stop, &time);
 
+      gst_segment_set_newsegment (&data->segment, update, rate, format,
+          start, stop, time);
       goto beach;
     }
     default:
index 789197f..e6d7ca9 100644 (file)
@@ -55,9 +55,7 @@ struct _GstCollectData
   GstPad               *pad;
   GstBuffer            *buffer;
   guint                         pos;
-  gint64                segment_start;
-  gint64                segment_stop;
-  gint64                stream_time;
+  GstSegment             segment;
 
   /*< private >*/
   gpointer               _gst_reserved[GST_PADDING];
index ea8c632..0502b8f 100644 (file)
@@ -324,8 +324,6 @@ static void
 gst_fake_src_init (GstFakeSrc * fakesrc, GstFakeSrcClass * g_class)
 {
   fakesrc->output = FAKE_SRC_FIRST_LAST_LOOP;
-  fakesrc->segment_start = -1;
-  fakesrc->segment_end = -1;
   fakesrc->buffer_count = 0;
   fakesrc->silent = DEFAULT_SILENT;
   fakesrc->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
@@ -687,12 +685,6 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
 
   src = GST_FAKE_SRC (basesrc);
 
-  if (src->buffer_count == src->segment_end) {
-    GST_INFO ("buffer_count reaches segment_end %d %d", src->buffer_count,
-        src->segment_end);
-    return GST_FLOW_UNEXPECTED;
-  }
-
   buf = gst_fake_src_create_buffer (src);
   GST_BUFFER_OFFSET (buf) = src->buffer_count++;
 
index 0ea04c4..783db23 100644 (file)
@@ -96,9 +96,7 @@ struct _GstFakeSrc {
   gint          datarate;
   gboolean      sync;
   GstClock     *clock;
-  gint64        segment_start;
-  gint64        segment_end;
-  gboolean      segment_loop;
+
   gint          num_buffers;
   gint          rt_num_buffers; /* we are going to change this at runtime */
   gint64        buffer_count;
index 37906b9..27c7e58 100644 (file)
@@ -376,8 +376,8 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
       GstClockReturn cret;
       GstClockTime timestamp;
 
-      timestamp = GST_BUFFER_TIMESTAMP (buf) - trans->segment_start;
-      timestamp += trans->segment_accum;
+      timestamp = gst_segment_to_running_time (&trans->segment,
+          GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf));
       timestamp += GST_ELEMENT (identity)->base_time;
 
       /* save id if we need to unlock */
index bae53c1..4a14654 100644 (file)
@@ -77,7 +77,11 @@ gst_segment_set_duration (GstSegment * segment, GstFormat format,
     gint64 duration)
 {
   g_return_if_fail (segment != NULL);
-  g_return_if_fail (segment->format == format);
+
+  if (segment->format == GST_FORMAT_UNDEFINED)
+    segment->format = format;
+  else
+    g_return_if_fail (segment->format == format);
 
   segment->duration = duration;
 }
@@ -95,7 +99,11 @@ gst_segment_set_last_stop (GstSegment * segment, GstFormat format,
     gint64 position)
 {
   g_return_if_fail (segment != NULL);
-  g_return_if_fail (segment->format == format);
+
+  if (segment->format == GST_FORMAT_UNDEFINED)
+    segment->format = format;
+  else
+    g_return_if_fail (segment->format == format);
 
   segment->last_stop = position;
 }
@@ -110,19 +118,26 @@ gst_segment_set_last_stop (GstSegment * segment, GstFormat format,
  * @cur: the seek start value
  * @stop_type: the seek method
  * @stop: the seek stop value
+ * @update: boolean holding whether an update the current segment is
+ *    needed.
  *
  * Update the segment structure with the field values of a seek event.
  */
 void
 gst_segment_set_seek (GstSegment * segment, gdouble rate,
     GstFormat format, GstSeekFlags flags,
-    GstSeekType cur_type, gint64 cur, GstSeekType stop_type, gint64 stop)
+    GstSeekType cur_type, gint64 cur,
+    GstSeekType stop_type, gint64 stop, gboolean * update)
 {
   gboolean update_stop, update_start;
 
   g_return_if_fail (rate != 0.0);
   g_return_if_fail (segment != NULL);
-  g_return_if_fail (segment->format == format);
+
+  if (segment->format == GST_FORMAT_UNDEFINED)
+    segment->format = format;
+  else
+    g_return_if_fail (segment->format == format);
 
   update_stop = update_start = TRUE;
 
@@ -199,6 +214,9 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
   segment->flags = flags;
   segment->start = cur;
   segment->stop = stop;
+
+  if (update)
+    *update = update_start || update_stop;
 }
 
 /**
@@ -222,6 +240,9 @@ gst_segment_set_newsegment (GstSegment * segment, gboolean update, gdouble rate,
   g_return_if_fail (rate != 0.0);
   g_return_if_fail (segment != NULL);
 
+  if (segment->format == GST_FORMAT_UNDEFINED)
+    segment->format = format;
+
   /* any other format with 0 also gives time 0, the other values are
    * invalid in the format though. */
   if (format != segment->format && start == 0) {
@@ -283,12 +304,22 @@ gint64
 gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
     gint64 position)
 {
-  gint64 result;
+  gint64 result, time;
 
   g_return_val_if_fail (segment != NULL, FALSE);
-  g_return_val_if_fail (segment->format == format, FALSE);
 
-  result = ((position - segment->start) / segment->abs_rate) + segment->time;
+  if (segment->format == GST_FORMAT_UNDEFINED)
+    segment->format = format;
+  else
+    g_return_val_if_fail (segment->format == format, FALSE);
+
+  if ((time = segment->time) == -1)
+    time = 0;
+
+  if (position != -1)
+    result = ((position - segment->start) / segment->abs_rate) + time;
+  else
+    result = -1;
 
   return result;
 }
@@ -313,10 +344,17 @@ gst_segment_to_running_time (GstSegment * segment, GstFormat format,
 {
   gint64 result;
 
-  g_return_val_if_fail (segment != NULL, FALSE);
-  g_return_val_if_fail (segment->format == format, FALSE);
+  g_return_val_if_fail (segment != NULL, -1);
 
-  result = ((position - segment->start) / segment->abs_rate) + segment->accum;
+  if (segment->format == GST_FORMAT_UNDEFINED)
+    segment->format = format;
+  else
+    g_return_val_if_fail (segment->format == format, -1);
+
+  if (position != -1)
+    result = ((position - segment->start) / segment->abs_rate) + segment->accum;
+  else
+    result = -1;
 
   return result;
 }
@@ -341,7 +379,11 @@ gst_segment_clip (GstSegment * segment, GstFormat format, gint64 start,
     gint64 stop, gint64 * clip_start, gint64 * clip_stop)
 {
   g_return_val_if_fail (segment != NULL, FALSE);
-  g_return_val_if_fail (segment->format == format, FALSE);
+
+  if (segment->format == GST_FORMAT_UNDEFINED)
+    segment->format = format;
+  else
+    g_return_val_if_fail (segment->format == format, FALSE);
 
   /* we need a valid start position */
   if (start == -1)
index 07115bd..d5eaedc 100644 (file)
@@ -72,7 +72,8 @@ void          gst_segment_set_last_stop       (GstSegment *segment, GstFormat format, gint64 p
 void           gst_segment_set_seek            (GstSegment *segment, gdouble rate, 
                                                 GstFormat format, GstSeekFlags flags, 
                                                 GstSeekType cur_type, gint64 cur,
-                                                GstSeekType stop_type, gint64 stop);
+                                                GstSeekType stop_type, gint64 stop,
+                                                gboolean *update);
 
 void           gst_segment_set_newsegment      (GstSegment *segment, gboolean update, gdouble rate,
                                                 GstFormat format, gint64 start, gint64 stop, gint64 time);
index f0c948a..cd5477e 100644 (file)
@@ -579,81 +579,28 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
         gboolean update;
         gdouble rate;
         GstFormat format;
-        gint64 segment_start;
-        gint64 segment_stop;
-        gint64 segment_time;
-        GstClockTime duration;
+        gint64 start;
+        gint64 stop;
+        gint64 time;
 
         /* the newsegment event is needed to bring the buffer timestamps to the
          * stream time and to drop samples outside of the playback segment. */
         gst_event_parse_newsegment (event, &update, &rate, &format,
-            &segment_start, &segment_stop, &segment_time);
+            &start, &stop, &time);
 
         basesink->have_newsegment = TRUE;
 
-        /* any other format with 0 also gives time 0, the other values are
-         * invalid as time though. */
-        if (format != GST_FORMAT_TIME && segment_start == 0) {
-          GST_DEBUG_OBJECT (basesink,
-              "non-time newsegment with start 0, coaxing into FORMAT_TIME");
-          format = GST_FORMAT_TIME;
-          if (segment_stop != 0)
-            segment_stop = -1;
-          if (segment_time != 0)
-            segment_time = -1;
-        }
-
-        if (format != GST_FORMAT_TIME) {
-          GST_DEBUG_OBJECT (basesink,
-              "received non time %d NEW_SEGMENT %" G_GINT64_FORMAT
-              " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT,
-              format, segment_start, segment_stop, segment_time);
-
-          /* this means this sink will not be able to clip or drop samples
-           * and timestamps have to start from 0. */
-          basesink->segment_start = -1;
-          basesink->segment_stop = -1;
-          basesink->segment_time = -1;
-          goto done_newsegment;
-        }
-        /* check if we really have a new segment or the previous one is
-         * closed */
-        if (!update) {
-          /* the new segment has to be aligned with the old segment.
-           * We first update the accumulated time of the previous
-           * segment. the accumulated time is used when syncing to the
-           * clock. A flush event sets the accumulated time back to 0
-           */
-          if (GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) {
-            duration = basesink->segment_stop - basesink->segment_start;
-          } else if (GST_CLOCK_TIME_IS_VALID (basesink->current_end)) {
-            /* else use last seen timestamp as segment stop */
-            duration = basesink->current_end - basesink->segment_start;
-          } else {
-            duration = 0;
-          }
-        } else {
-          duration = segment_start - basesink->segment_start;
-        }
-
-        /* use previous rate to calculate duration */
-        basesink->segment_accum += gst_gdouble_to_guint64 (
-            (gst_guint64_to_gdouble (duration) / ABS (basesink->segment_rate)));
-        /* then update the current segment */
-        basesink->segment_rate = rate;
-        basesink->segment_start = segment_start;
-        basesink->segment_stop = segment_stop;
-        basesink->segment_time = segment_time;
+        gst_segment_set_newsegment (&basesink->segment, update, rate, format,
+            start, stop, time);
 
         GST_DEBUG_OBJECT (basesink,
             "received NEWSEGMENT %" GST_TIME_FORMAT " -- %"
             GST_TIME_FORMAT ", time %" GST_TIME_FORMAT ", accum %"
             GST_TIME_FORMAT,
-            GST_TIME_ARGS (basesink->segment_start),
-            GST_TIME_ARGS (basesink->segment_stop),
-            GST_TIME_ARGS (basesink->segment_time),
-            GST_TIME_ARGS (basesink->segment_accum));
-      done_newsegment:
+            GST_TIME_ARGS (basesink->segment.start),
+            GST_TIME_ARGS (basesink->segment.stop),
+            GST_TIME_ARGS (basesink->segment.time),
+            GST_TIME_ARGS (basesink->segment.accum));
         break;
       }
       default:
@@ -669,8 +616,8 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
           ("Received buffer without a new-segment. Cannot sync to clock."));
       basesink->have_newsegment = TRUE;
       /* this means this sink will not be able to sync to the clock */
-      basesink->segment_start = -1;
-      basesink->segment_stop = -1;
+      basesink->segment.start = -1;
+      basesink->segment.stop = -1;
     }
 
     /* check if the buffer needs to be dropped */
@@ -685,28 +632,10 @@ gst_base_sink_handle_object (GstBaseSink * basesink, GstPad * pad,
           ", end: %" GST_TIME_FORMAT, GST_TIME_ARGS (start),
           GST_TIME_ARGS (end));
 
-      /* need to drop if the timestamp is not between segment_start and
-       * segment_stop. we check if the complete sample is outside of the
-       * range since the sink might be able to clip the sample. */
-      if (GST_CLOCK_TIME_IS_VALID (end) &&
-          GST_CLOCK_TIME_IS_VALID (basesink->segment_start)) {
-        if (end <= basesink->segment_start) {
-          GST_DEBUG_OBJECT (basesink,
-              "buffer end %" GST_TIME_FORMAT " <= segment start %"
-              GST_TIME_FORMAT ", dropping buffer", GST_TIME_ARGS (end),
-              GST_TIME_ARGS (basesink->segment_start));
+      if (GST_CLOCK_TIME_IS_VALID (start)) {
+        if (!gst_segment_clip (&basesink->segment, GST_FORMAT_TIME,
+                (gint64) start, (gint64) end, NULL, NULL))
           goto dropping;
-        }
-      }
-      if (GST_CLOCK_TIME_IS_VALID (start) &&
-          GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) {
-        if (basesink->segment_stop <= start) {
-          GST_DEBUG_OBJECT (basesink,
-              "buffer start %" GST_TIME_FORMAT " >= segment stop %"
-              GST_TIME_FORMAT ", dropping buffer", GST_TIME_ARGS (start),
-              GST_TIME_ARGS (basesink->segment_stop));
-          goto dropping;
-        }
       }
     }
     basesink->preroll_queued++;
@@ -917,13 +846,7 @@ gst_base_sink_event (GstPad * pad, GstEvent * event)
       basesink->flushing = FALSE;
       GST_OBJECT_UNLOCK (basesink);
       /* we need new segment info after the flush. */
-      basesink->segment_start = -1;
-      basesink->segment_stop = -1;
-      basesink->current_start = -1;
-      basesink->current_end = -1;
-      GST_DEBUG_OBJECT (basesink, "reset accum %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (basesink->segment_accum));
-      basesink->segment_accum = 0;
+      gst_segment_init (&basesink->segment, GST_FORMAT_TIME);
       GST_STREAM_UNLOCK (pad);
 
       GST_DEBUG_OBJECT (basesink, "event unref %p %p", basesink, event);
@@ -1004,9 +927,8 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
 {
   GstClockReturn result = GST_CLOCK_OK;
   GstClockTime start, end;
-  GstClockTimeDiff stream_start, stream_end;
+  gint64 cstart, cend;
   GstBaseSinkClass *bclass;
-  gboolean start_valid, end_valid;
 
   bclass = GST_BASE_SINK_GET_CLASS (basesink);
 
@@ -1014,61 +936,27 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
   if (bclass->get_times)
     bclass->get_times (basesink, buffer, &start, &end);
 
-  start_valid = GST_CLOCK_TIME_IS_VALID (start);
-  end_valid = GST_CLOCK_TIME_IS_VALID (end);
-
   GST_DEBUG_OBJECT (basesink, "got times start: %" GST_TIME_FORMAT
       ", end: %" GST_TIME_FORMAT, GST_TIME_ARGS (start), GST_TIME_ARGS (end));
 
   /* if we don't have a timestamp, we don't sync */
-  if (!start_valid) {
+  if (!GST_CLOCK_TIME_IS_VALID (start)) {
     GST_DEBUG_OBJECT (basesink, "start not valid");
     goto done;
   }
 
   /* save last times seen. */
-  basesink->current_start = start;
-  if (end_valid)
-    basesink->current_end = end;
+  if (GST_CLOCK_TIME_IS_VALID (end))
+    gst_segment_set_last_stop (&basesink->segment, GST_FORMAT_TIME,
+        (gint64) end);
   else
-    basesink->current_end = start;
+    gst_segment_set_last_stop (&basesink->segment, GST_FORMAT_TIME,
+        (gint64) start);
 
-  if (GST_CLOCK_TIME_IS_VALID (basesink->segment_stop)) {
-    /* check if not outside of the segment range, start is
-     * always valid here. */
-    if (start > basesink->segment_stop)
-      goto out_of_segment;
-  }
-
-  /* bring timestamp to stream time using last segment offset. */
-  if (GST_CLOCK_TIME_IS_VALID (basesink->segment_start)) {
-    /* check if not outside of the segment range */
-    if (end_valid && end < basesink->segment_start)
-      goto out_of_segment;
-
-    stream_start = (gint64) start - basesink->segment_start;
-    stream_end = (gint64) end - basesink->segment_start;
-
-    if (stream_start < 0) {
-      GST_DEBUG_OBJECT (basesink, "stream_start negative, invalid");
-      goto done;
-    }
-  } else {
-    stream_start = (gint64) start;
-    stream_end = (gint64) end;
-  }
-
-
-  /* correct for rate */
-  if (basesink->segment_rate != 0.0) {
-    stream_start /= ABS (basesink->segment_rate);
-    if (end_valid)
-      stream_end /= ABS (basesink->segment_rate);
-  }
-
-  stream_start += basesink->segment_accum;
-  if (end_valid)
-    stream_end += basesink->segment_accum;
+  /* clip */
+  if (!gst_segment_clip (&basesink->segment, GST_FORMAT_TIME,
+          (gint64) start, (gint64) end, &cstart, &cend))
+    goto out_of_segment;
 
   if (!basesink->sync) {
     GST_DEBUG_OBJECT (basesink, "no need to sync");
@@ -1078,6 +966,13 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
   /* now do clocking */
   if (basesink->clock) {
     GstClockTime base_time;
+    GstClockTimeDiff stream_start, stream_end;
+
+    stream_start =
+        gst_segment_to_running_time (&basesink->segment, GST_FORMAT_TIME,
+        cstart);
+    stream_end =
+        gst_segment_to_running_time (&basesink->segment, GST_FORMAT_TIME, cend);
 
     GST_OBJECT_LOCK (basesink);
 
@@ -1090,7 +985,7 @@ gst_base_sink_do_sync (GstBaseSink * basesink, GstBuffer * buffer)
 
     /* also save end_time of this buffer so that we can wait
      * to signal EOS */
-    if (end_valid)
+    if (GST_CLOCK_TIME_IS_VALID (stream_end))
       basesink->end_time = stream_end + base_time;
     else
       basesink->end_time = GST_CLOCK_TIME_NONE;
@@ -1386,7 +1281,7 @@ gst_base_sink_activate_pull (GstPad * pad, gboolean active)
       } else {
         if (gst_pad_activate_pull (peer, TRUE)) {
           basesink->have_newsegment = TRUE;
-          basesink->segment_start = basesink->segment_stop = 0;
+          gst_segment_init (&basesink->segment, GST_FORMAT_TIME);
 
           /* set the pad mode before starting the task so that it's in the
              correct state for the new thread... */
@@ -1467,7 +1362,7 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
       GST_OBJECT_LOCK (basesink);
       if ((clock = GST_ELEMENT_CLOCK (basesink))) {
         GstClockTime now;
-        gint64 segment_time;
+        gint64 time;
 
         gst_object_ref (clock);
         GST_OBJECT_UNLOCK (basesink);
@@ -1475,18 +1370,18 @@ gst_base_sink_get_position (GstBaseSink * basesink, GstFormat format,
         now = gst_clock_get_time (clock);
 
         GST_OBJECT_LOCK (basesink);
-        if (GST_CLOCK_TIME_IS_VALID (basesink->segment_time))
-          segment_time = basesink->segment_time;
+        if (GST_CLOCK_TIME_IS_VALID (basesink->segment.time))
+          time = basesink->segment.time;
         else
-          segment_time = 0;
+          time = 0;
 
         *cur = now - GST_ELEMENT_CAST (basesink)->base_time -
-            basesink->segment_accum + segment_time;
+            basesink->segment.accum + time;
 
         GST_DEBUG_OBJECT (basesink,
             "now %" GST_TIME_FORMAT " + segment_time %" GST_TIME_FORMAT " = %"
             GST_TIME_FORMAT, GST_TIME_ARGS (now),
-            GST_TIME_ARGS (segment_time), GST_TIME_ARGS (*cur));
+            GST_TIME_ARGS (time), GST_TIME_ARGS (*cur));
 
         gst_object_unref (clock);
 
@@ -1547,8 +1442,8 @@ gst_base_sink_query (GstElement * element, GstQuery * query)
     case GST_QUERY_SEGMENT:
     {
       /* FIXME, bring start/stop to stream time */
-      gst_query_set_segment (query, basesink->segment_rate,
-          GST_FORMAT_TIME, basesink->segment_start, basesink->segment_stop);
+      gst_query_set_segment (query, basesink->segment.rate,
+          GST_FORMAT_TIME, basesink->segment.start, basesink->segment.stop);
       break;
     }
     case GST_QUERY_SEEKING:
@@ -1585,15 +1480,8 @@ gst_base_sink_change_state (GstElement * element, GstStateChange transition)
       GST_DEBUG_OBJECT (basesink, "READY to PAUSED, need preroll to FALSE");
       basesink->need_preroll = TRUE;
       GST_PREROLL_UNLOCK (basesink->sinkpad);
+      gst_segment_init (&basesink->segment, GST_FORMAT_TIME);
       basesink->have_newsegment = FALSE;
-      basesink->segment_rate = 1.0;
-      basesink->segment_start = 0;
-      basesink->segment_stop = -1;
-      basesink->segment_time = 0;
-      basesink->current_start = -1;
-      basesink->current_duration = -1;
-      basesink->current_end = -1;
-      basesink->segment_accum = 0;
       ret = GST_STATE_CHANGE_ASYNC;
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
index f3fb83a..bb87cb5 100644 (file)
@@ -80,15 +80,7 @@ struct _GstBaseSink {
 
   /*< protected >*/ /* with STREAM_LOCK */
   gboolean      have_newsegment;
-  gdouble       segment_rate;
-  gint64        segment_start;
-  gint64        segment_stop;
-  gint64        segment_time;
-  gint64        segment_accum;
-
-  gint64        current_start;
-  gint64        current_duration;
-  gint64        current_end;
+  GstSegment     segment;
 
   /*< private >*/ /* with LOCK */
   GstClock     *clock;
index 9080623..d57e6c3 100644 (file)
@@ -229,8 +229,7 @@ gst_base_src_init (GstBaseSrc * basesrc, gpointer g_class)
 
   basesrc->blocksize = DEFAULT_BLOCKSIZE;
   basesrc->clock_id = NULL;
-  basesrc->segment_start = 0;
-  basesrc->segment_end = -1;
+  gst_segment_init (&basesrc->segment, GST_FORMAT_BYTES);
 
   GST_OBJECT_FLAG_UNSET (basesrc, GST_BASE_SRC_STARTED);
 
@@ -411,9 +410,9 @@ gst_base_src_query (GstPad * pad, GstQuery * query)
     {
       gint64 start, stop;
 
-      start = src->segment_start;
+      start = src->segment.start;
       /* no end segment configured, current size then */
-      if ((stop = src->segment_end) == -1)
+      if ((stop = src->segment.stop) == -1)
         stop = src->size;
 
       /* FIXME, we can't report our rate as we did not store it, d'oh!.
@@ -448,11 +447,11 @@ gst_base_src_default_newsegment (GstBaseSrc * src)
   GstEvent *event;
 
   GST_DEBUG_OBJECT (src, "Sending newsegment from %" G_GINT64_FORMAT
-      " to %" G_GINT64_FORMAT, src->segment_start, src->segment_end);
+      " to %" G_GINT64_FORMAT, src->segment.start, src->segment.stop);
 
   event = gst_event_new_newsegment (FALSE, 1.0,
-      GST_FORMAT_BYTES, src->segment_start, src->segment_end,
-      src->segment_start);
+      GST_FORMAT_BYTES, src->segment.start, src->segment.stop,
+      src->segment.start);
 
   return gst_pad_push_event (src->srcpad, event);
 }
@@ -471,7 +470,7 @@ gst_base_src_newsegment (GstBaseSrc * src)
   return result;
 }
 
-/* based on the event parameters configure the segment_start/stop
+/* based on the event parameters configure the segment.start/stop
  * times. Called with STREAM_LOCK.
  */
 static gboolean
@@ -482,84 +481,20 @@ gst_base_src_configure_segment (GstBaseSrc * src, GstEvent * event)
   GstSeekFlags flags;
   GstSeekType cur_type, stop_type;
   gint64 cur, stop;
-  gboolean update_stop, update_start;
+  gboolean update;
 
   gst_event_parse_seek (event, &rate, &format, &flags,
       &cur_type, &cur, &stop_type, &stop);
 
-  /* parse the loop flag */
-  /* FIXME, need to store other flags and rate too */
-  src->segment_loop = (flags & GST_SEEK_FLAG_SEGMENT) != 0;
-
-  /* assume we'll update both start and stop values */
-  update_start = TRUE;
-  update_stop = TRUE;
-
-  /* perform the seek, segment_start is never invalid */
-  switch (cur_type) {
-    case GST_SEEK_TYPE_NONE:
-      /* no update to segment */
-      cur = src->segment_start;
-      update_start = FALSE;
-      break;
-    case GST_SEEK_TYPE_SET:
-      /* cur holds desired position */
-      break;
-    case GST_SEEK_TYPE_CUR:
-      /* add cur to currently configure segment */
-      cur = src->segment_start + cur;
-      break;
-    case GST_SEEK_TYPE_END:
-      /* add cur to total length */
-      cur = src->size + cur;
-      break;
-  }
-  /* bring in sane range */
-  if (src->size != -1)
-    cur = CLAMP (cur, 0, src->size);
-  else
-    cur = MAX (cur, 0);
-
-  /* segment_end can be -1 if we have not configured a stop. */
-  switch (stop_type) {
-    case GST_SEEK_TYPE_NONE:
-      stop = src->segment_end;
-      update_stop = FALSE;
-      break;
-    case GST_SEEK_TYPE_SET:
-      /* stop folds required value */
-      break;
-    case GST_SEEK_TYPE_CUR:
-      if (src->segment_end != -1)
-        stop = src->segment_end + stop;
-      else
-        stop = -1;
-      break;
-    case GST_SEEK_TYPE_END:
-      if (src->size != -1)
-        stop = src->size + stop;
-      else
-        stop = -1;
-      break;
-  }
-
-  /* if we have a valid stop time, make sure it is clipped */
-  if (stop != -1) {
-    if (src->size != -1)
-      stop = CLAMP (stop, 0, src->size);
-    else
-      stop = MAX (stop, 0);
-  }
-
-  src->segment_start = cur;
-  src->segment_end = stop;
+  gst_segment_set_seek (&src->segment, rate, format, flags,
+      cur_type, cur, stop_type, stop, &update);
 
   /* update our offset if it was updated */
-  if (update_start)
+  if (update)
     src->offset = cur;
 
   GST_DEBUG_OBJECT (src, "segment configured from %" G_GINT64_FORMAT
-      " to %" G_GINT64_FORMAT, src->segment_start, src->segment_end);
+      " to %" G_GINT64_FORMAT, src->segment.start, src->segment.stop);
 
   return TRUE;
 }
@@ -567,9 +502,9 @@ gst_base_src_configure_segment (GstBaseSrc * src, GstEvent * event)
 /* this code implements the seeking. It is a good example
  * handling all cases (modulo the FIXMEs).
  *
- * A seek updates the currently configured segment_start
- * and segment_stop values based on the SEEK_TYPE. If the
- * segment_start value is updated, a seek to this new position
+ * A seek updates the currently configured segment.start
+ * and segment.stop values based on the SEEK_TYPE. If the
+ * segment.start value is updated, a seek to this new position
  * should be performed.
  *
  * The seek can only be executed when we are not currently
@@ -592,13 +527,13 @@ gst_base_src_configure_segment (GstBaseSrc * src, GstEvent * event)
  * can continue the seek. A non-flushing seek is normally done in a 
  * running pipeline to perform seamless playback.
  *
- * After updating the segment_start/stop values, we prepare for
+ * After updating the segment.start/stop values, we prepare for
  * streaming again. We push out a FLUSH_STOP to make the peer pad
  * accept data again and we start our task again.
  *
  * A segment seek posts a message on the bus saying that the playback
  * of the segment started. We store the segment flag internally because
- * when we reach the segment_stop we have to post a segment_done
+ * when we reach the segment.stop we have to post a segment.done
  * instead of EOS when doing a segment seek.
  */
 static gboolean
@@ -648,11 +583,11 @@ gst_base_src_do_seek (GstBaseSrc * src, GstEvent * event)
    * thread. We could opt to send it here too. */
   src->need_newsegment = TRUE;
 
-  if (src->segment_loop) {
+  if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
     /* FIXME subclasses should be able to provide other formats */
     gst_element_post_message (GST_ELEMENT (src),
         gst_message_new_segment_start (GST_OBJECT (src), GST_FORMAT_BYTES,
-            src->segment_start));
+            src->segment.start));
   }
 
   /* and restart the task in case it got paused explicitely or by
@@ -906,16 +841,16 @@ gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
     goto no_function;
 
   /* the max amount of bytes to read is the total size or
-   * up to the segment_end if present. */
-  if (src->segment_end != -1)
-    maxsize = MIN (src->size, src->segment_end);
+   * up to the segment.stop if present. */
+  if (src->segment.stop != -1)
+    maxsize = MIN (src->size, src->segment.stop);
   else
     maxsize = src->size;
 
   GST_DEBUG_OBJECT (src,
       "reading offset %" G_GUINT64_FORMAT ", length %u, size %" G_GINT64_FORMAT
-      ", segment_end %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset,
-      length, src->size, src->segment_end, maxsize);
+      ", segment.stop %" G_GINT64_FORMAT ", maxsize %" G_GINT64_FORMAT, offset,
+      length, src->size, src->segment.stop, maxsize);
 
   /* check size */
   if (maxsize != -1) {
@@ -927,8 +862,8 @@ gst_base_src_get_range (GstBaseSrc * src, guint64 offset, guint length,
       if (bclass->get_size)
         bclass->get_size (src, &src->size);
 
-      if (src->segment_end != -1)
-        maxsize = MIN (src->size, src->segment_end);
+      if (src->segment.stop != -1)
+        maxsize = MIN (src->size, src->segment.stop);
       else
         maxsize = src->size;
 
@@ -1072,11 +1007,11 @@ eos:
   {
     GST_DEBUG_OBJECT (src, "going to EOS, getrange returned UNEXPECTED");
     gst_pad_pause_task (pad);
-    if (src->segment_loop) {
+    if (src->segment.flags & GST_SEEK_FLAG_SEGMENT) {
       /* FIXME, subclass might want to use another format */
       gst_element_post_message (GST_ELEMENT (src),
           gst_message_new_segment_done (GST_OBJECT (src),
-              GST_FORMAT_BYTES, src->segment_end));
+              GST_FORMAT_BYTES, src->segment.stop));
     } else {
       gst_pad_push_event (pad, gst_event_new_eos ());
     }
@@ -1493,9 +1428,7 @@ gst_base_src_change_state (GstElement * element, GstStateChange transition)
       /* we always run from start to end when in READY, after putting
        * the element to READY a seek can be done on the element to
        * configure the segment when going to PAUSED. */
-      basesrc->segment_loop = FALSE;
-      basesrc->segment_start = 0;
-      basesrc->segment_end = -1;
+      gst_segment_init (&basesrc->segment, GST_FORMAT_BYTES);
       basesrc->offset = 0;
       break;
     case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
@@ -1510,9 +1443,7 @@ gst_base_src_change_state (GstElement * element, GstStateChange transition)
       if (!gst_base_src_stop (basesrc))
         goto error_stop;
       /* we always run from start to end when in READY */
-      basesrc->segment_loop = FALSE;
-      basesrc->segment_start = 0;
-      basesrc->segment_end = -1;
+      gst_segment_init (&basesrc->segment, GST_FORMAT_BYTES);
       basesrc->offset = 0;
       break;
     case GST_STATE_CHANGE_READY_TO_NULL:
index f62f1c0..1d788a5 100644 (file)
@@ -84,9 +84,7 @@ struct _GstBaseSrc {
   GstClockTime   end_time;
 
   /* MT-protected (with STREAM_LOCK) */
-  gint64        segment_start; /* start and end positions for seeking */
-  gint64        segment_end;
-  gboolean      segment_loop;
+  GstSegment     segment;
   gboolean      need_newsegment;
 
   guint64       offset;        /* current offset in the resource */
index ba50418..e856c51 100644 (file)
@@ -854,6 +854,7 @@ gst_base_transform_prepare_output_buf (GstBaseTransform * trans,
     if (G_UNLIKELY (!gst_caps_is_equal (out_caps, GST_BUFFER_CAPS (*out_buf)))) {
       /* FIXME, it is possible we can reconfigure the transform with new caps at this
        * point but for now we just create a buffer ourselves */
+      gst_buffer_unref (*out_buf);
       *out_buf = gst_buffer_new_and_alloc (out_size);
       gst_buffer_set_caps (*out_buf, out_caps);
     }
@@ -1056,13 +1057,7 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
       GST_STREAM_LOCK (pad);
       unlock = TRUE;
       /* we need new segment info after the flush. */
-      trans->segment_rate = 1.0;
-      trans->segment_start = -1;
-      trans->segment_stop = -1;
-      trans->segment_base = -1;
-      GST_DEBUG_OBJECT (trans, "reset accum %" GST_TIME_FORMAT,
-          GST_TIME_ARGS (trans->segment_accum));
-      trans->segment_accum = 0;
+      gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);
       break;
     case GST_EVENT_EOS:
       GST_STREAM_LOCK (pad);
@@ -1076,7 +1071,7 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
     {
       GstFormat format;
       gdouble rate;
-      gint64 start, stop, time, duration;
+      gint64 start, stop, time;
       gboolean update;
 
       GST_STREAM_LOCK (pad);
@@ -1084,63 +1079,25 @@ gst_base_transform_event (GstPad * pad, GstEvent * event)
       gst_event_parse_newsegment (event, &update, &rate, &format, &start, &stop,
           &time);
 
-      /* any other format with 0 also gives time 0, the other values are
-       * invalid as time though. */
-      if (format != GST_FORMAT_TIME) {
-        GST_DEBUG_OBJECT (trans,
-            "non-time newsegment with start 0, coaxing into FORMAT_TIME");
-        format = GST_FORMAT_TIME;
-        if (start != 0)
-          start = -1;
-        if (stop != 0)
-          stop = -1;
-        if (time != 0)
-          time = -1;
-      }
-
-      /* check if we really have a new segment or the previous one is
-       * closed */
-      if (!update) {
-        /* the new segment has to be aligned with the old segment.
-         * We first update the accumulated time of the previous
-         * segment. the accumulated time is used when syncing to the
-         * clock. A flush event sets the accumulated time back to 0
-         */
-        if (GST_CLOCK_TIME_IS_VALID (trans->segment_stop)) {
-          duration = trans->segment_stop - trans->segment_start;
-        } else {
-          duration = 0;
-        }
-      } else {
-        if (GST_CLOCK_TIME_IS_VALID (start))
-          duration = start - trans->segment_start;
-        else
-          duration = 0;
-      }
+      gst_segment_set_newsegment (&trans->segment, update, rate, format, start,
+          stop, time);
 
       trans->have_newsegment = TRUE;
 
-      trans->segment_accum += gst_gdouble_to_guint64 (
-          (gst_guint64_to_gdouble (duration) / ABS (trans->segment_rate)));;
-      trans->segment_rate = rate;
-      trans->segment_start = start;
-      trans->segment_stop = stop;
-      trans->segment_base = time;
-
       if (format == GST_FORMAT_TIME) {
         GST_DEBUG_OBJECT (trans, "received NEW_SEGMENT %" GST_TIME_FORMAT
             " -- %" GST_TIME_FORMAT ", time %" GST_TIME_FORMAT
             ", accum %" GST_TIME_FORMAT,
-            GST_TIME_ARGS (trans->segment_start),
-            GST_TIME_ARGS (trans->segment_stop),
-            GST_TIME_ARGS (trans->segment_base),
-            GST_TIME_ARGS (trans->segment_accum));
+            GST_TIME_ARGS (trans->segment.start),
+            GST_TIME_ARGS (trans->segment.stop),
+            GST_TIME_ARGS (trans->segment.time),
+            GST_TIME_ARGS (trans->segment.accum));
       } else {
         GST_DEBUG_OBJECT (trans, "received NEW_SEGMENT %" G_GINT64_FORMAT
             " -- %" G_GINT64_FORMAT ", time %" G_GINT64_FORMAT
             ", accum %" G_GINT64_FORMAT,
-            trans->segment_start, trans->segment_stop,
-            trans->segment_base, trans->segment_accum);
+            trans->segment.start, trans->segment.stop,
+            trans->segment.time, trans->segment.accum);
       }
       break;
     }
@@ -1432,11 +1389,7 @@ gst_base_transform_change_state (GstElement * element,
       GST_DEBUG_OBJECT (trans, "have_same_caps %d", trans->have_same_caps);
       trans->negotiated = FALSE;
       trans->have_newsegment = FALSE;
-      trans->segment_rate = 1.0;
-      trans->segment_start = 0;
-      trans->segment_stop = -1;
-      trans->segment_base = 0;
-      trans->segment_accum = 0;
+      gst_segment_init (&trans->segment, GST_FORMAT_UNDEFINED);
       GST_OBJECT_UNLOCK (trans);
       break;
     case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
index 77a4268..fdd4ac1 100644 (file)
@@ -65,6 +65,7 @@ struct _GstBaseTransform {
   guint                 cache_caps1_size;
   GstCaps      *cache_caps2;
   guint                 cache_caps2_size;
+  gboolean      have_same_caps;
 
   gboolean      delay_configure;
   gboolean      pending_configure;
@@ -73,22 +74,12 @@ struct _GstBaseTransform {
   gboolean       have_newsegment;
 
   /* MT-protected (with STREAM_LOCK) */
-  gdouble        segment_rate;
-  gint64         segment_start;
-  gint64         segment_stop;
-  gint64         segment_base;
-
-  union {
-    /* FIXME: When adjusting the padding, move this to a nice place in the structure */
-    /* Set if caps on each pad are equal */
-    struct {
-      gboolean  have_same_caps;
-      GMutex   *transform_lock;
-      gint64     segment_accum;
-    };
-    /*< private >*/
-    gpointer       _gst_reserved[GST_PADDING-1+1];
-  };
+  GstSegment     segment;
+
+  GMutex       *transform_lock;
+
+  /*< private >*/
+  gpointer       _gst_reserved[GST_PADDING];
 };
 
 /**
@@ -165,15 +156,16 @@ struct _GstBaseTransformClass {
   gpointer       _gst_reserved[GST_PADDING - 2];
 };
 
-void           gst_base_transform_set_passthrough (GstBaseTransform *trans,
-                   gboolean passthrough);
-gboolean       gst_base_transform_is_passthrough (GstBaseTransform *trans);
+GType           gst_base_transform_get_type         (void);
+
+void           gst_base_transform_set_passthrough  (GstBaseTransform *trans,
+                                                    gboolean passthrough);
+gboolean       gst_base_transform_is_passthrough   (GstBaseTransform *trans);
 
-void           gst_base_transform_set_in_place (GstBaseTransform *trans,
-                   gboolean in_place);
-gboolean       gst_base_transform_is_in_place (GstBaseTransform *trans);
+void           gst_base_transform_set_in_place     (GstBaseTransform *trans,
+                                                    gboolean in_place);
+gboolean       gst_base_transform_is_in_place      (GstBaseTransform *trans);
 
-GType gst_base_transform_get_type (void);
 
 G_END_DECLS
 
index de08df4..d3a48fc 100644 (file)
@@ -196,6 +196,7 @@ gst_collect_pads_add_pad (GstCollectPads * pads, GstPad * pad, guint size)
   data->collect = pads;
   data->pad = pad;
   data->buffer = NULL;
+  gst_segment_init (&data->segment, GST_FORMAT_UNDEFINED);
 
   GST_OBJECT_LOCK (pads);
   pads->data = g_slist_append (pads->data, data);
@@ -599,20 +600,16 @@ gst_collect_pads_event (GstPad * pad, GstEvent * event)
     }
     case GST_EVENT_NEWSEGMENT:
     {
-      gint64 segment_start, segment_stop, stream_time;
-      gdouble segment_rate;
+      gint64 start, stop, time;
+      gdouble rate;
       GstFormat format;
       gboolean update;
 
-      gst_event_parse_newsegment (event, &update, &segment_rate, &format,
-          &segment_start, &segment_stop, &stream_time);
-
-      if (format == GST_FORMAT_TIME) {
-        data->segment_start = segment_start;
-        data->segment_stop = segment_stop;
-        data->stream_time = stream_time;
-      }
+      gst_event_parse_newsegment (event, &update, &rate, &format,
+          &start, &stop, &time);
 
+      gst_segment_set_newsegment (&data->segment, update, rate, format,
+          start, stop, time);
       goto beach;
     }
     default:
index 789197f..e6d7ca9 100644 (file)
@@ -55,9 +55,7 @@ struct _GstCollectData
   GstPad               *pad;
   GstBuffer            *buffer;
   guint                         pos;
-  gint64                segment_start;
-  gint64                segment_stop;
-  gint64                stream_time;
+  GstSegment             segment;
 
   /*< private >*/
   gpointer               _gst_reserved[GST_PADDING];
index ea8c632..0502b8f 100644 (file)
@@ -324,8 +324,6 @@ static void
 gst_fake_src_init (GstFakeSrc * fakesrc, GstFakeSrcClass * g_class)
 {
   fakesrc->output = FAKE_SRC_FIRST_LAST_LOOP;
-  fakesrc->segment_start = -1;
-  fakesrc->segment_end = -1;
   fakesrc->buffer_count = 0;
   fakesrc->silent = DEFAULT_SILENT;
   fakesrc->signal_handoffs = DEFAULT_SIGNAL_HANDOFFS;
@@ -687,12 +685,6 @@ gst_fake_src_create (GstBaseSrc * basesrc, guint64 offset, guint length,
 
   src = GST_FAKE_SRC (basesrc);
 
-  if (src->buffer_count == src->segment_end) {
-    GST_INFO ("buffer_count reaches segment_end %d %d", src->buffer_count,
-        src->segment_end);
-    return GST_FLOW_UNEXPECTED;
-  }
-
   buf = gst_fake_src_create_buffer (src);
   GST_BUFFER_OFFSET (buf) = src->buffer_count++;
 
index 0ea04c4..783db23 100644 (file)
@@ -96,9 +96,7 @@ struct _GstFakeSrc {
   gint          datarate;
   gboolean      sync;
   GstClock     *clock;
-  gint64        segment_start;
-  gint64        segment_end;
-  gboolean      segment_loop;
+
   gint          num_buffers;
   gint          rt_num_buffers; /* we are going to change this at runtime */
   gint64        buffer_count;
index 37906b9..27c7e58 100644 (file)
@@ -376,8 +376,8 @@ gst_identity_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
       GstClockReturn cret;
       GstClockTime timestamp;
 
-      timestamp = GST_BUFFER_TIMESTAMP (buf) - trans->segment_start;
-      timestamp += trans->segment_accum;
+      timestamp = gst_segment_to_running_time (&trans->segment,
+          GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf));
       timestamp += GST_ELEMENT (identity)->base_time;
 
       /* save id if we need to unlock */
index b4e2f5b..e32715e 100644 (file)
@@ -27,13 +27,15 @@ GST_START_TEST (segment_seek_nosize)
   GstSegment segment;
   gboolean res;
   gint64 cstart, cstop;
+  gboolean update;
 
   gst_segment_init (&segment, GST_FORMAT_BYTES);
 
   /* configure segment to start 100 */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == -1);
 
@@ -41,7 +43,8 @@ GST_START_TEST (segment_seek_nosize)
    * size is unknown. */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100, &update);
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == -1);
 
@@ -99,7 +102,8 @@ GST_START_TEST (segment_seek_nosize)
   /* add 100 to start, set stop to 300 */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300, &update);
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 300);
 
@@ -107,7 +111,8 @@ GST_START_TEST (segment_seek_nosize)
    * nothing should be updated in the segment. */
   ASSERT_CRITICAL (gst_segment_set_seek (&segment, 1.0,
           GST_FORMAT_BYTES,
-          GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200));
+          GST_SEEK_FLAG_NONE,
+          GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200, &update));
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 300);
 
@@ -115,7 +120,8 @@ GST_START_TEST (segment_seek_nosize)
    * unknown. */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_END, -300, GST_SEEK_TYPE_END, -100);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_END, -300, GST_SEEK_TYPE_END, -100, &update);
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 300);
 
@@ -193,6 +199,7 @@ GST_START_TEST (segment_seek_size)
   GstSegment segment;
   gboolean res;
   gint64 cstart, cstop;
+  gboolean update;
 
   gst_segment_init (&segment, GST_FORMAT_BYTES);
   gst_segment_set_duration (&segment, GST_FORMAT_BYTES, 200);
@@ -200,7 +207,8 @@ GST_START_TEST (segment_seek_size)
   /* configure segment to start 100 */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_SET, 100, GST_SEEK_TYPE_NONE, -1, &update);
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == -1);
 
@@ -208,7 +216,8 @@ GST_START_TEST (segment_seek_size)
    * since we did not set it before. */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, 200, GST_SEEK_TYPE_CUR, -100, &update);
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == -1);
 
@@ -273,7 +282,8 @@ GST_START_TEST (segment_seek_size)
   /* add 100 to start, set stop to 300, stop clips to 200 */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 300, &update);
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 200);
 
@@ -281,14 +291,16 @@ GST_START_TEST (segment_seek_size)
    * to duration */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_CUR, 100, GST_SEEK_TYPE_SET, 200, &update);
   fail_unless (segment.start == 200);
   fail_unless (segment.stop == 200);
 
   /* seek relative to end */
   gst_segment_set_seek (&segment, 1.0,
       GST_FORMAT_BYTES,
-      GST_SEEK_FLAG_NONE, GST_SEEK_TYPE_END, -100, GST_SEEK_TYPE_END, -20);
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_END, -100, GST_SEEK_TYPE_END, -20, &update);
   fail_unless (segment.start == 100);
   fail_unless (segment.stop == 180);