docs/design/part-synchronisation.txt: Small updates.
authorWim Taymans <wim.taymans@gmail.com>
Wed, 19 Dec 2007 12:48:18 +0000 (12:48 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Wed, 19 Dec 2007 12:48:18 +0000 (12:48 +0000)
Original commit message from CVS:
* docs/design/part-synchronisation.txt:
Small updates.
* gst/gstsegment.c: (gst_segment_set_seek),
(gst_segment_set_newsegment_full), (gst_segment_to_stream_time),
(gst_segment_to_running_time):
The seek format can be different from the segment format when the start
and stop values are not to be updated, when we only do a rate change for
example.
* tests/check/gst/gstsegment.c: (GST_START_TEST),
(gst_segment_suite):
Add a testcase for the rate-only seeks, checking that the format is
correctly ignored when start and stop are not updated.

ChangeLog
common
docs/design/part-synchronisation.txt
gst/gstsegment.c
tests/check/gst/gstsegment.c

index 69de672..f3ee6ea 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2007-12-19  Wim Taymans  <wim.taymans@collabora.co.uk>
+
+       * docs/design/part-synchronisation.txt:
+       Small updates.
+
+       * gst/gstsegment.c: (gst_segment_set_seek),
+       (gst_segment_set_newsegment_full), (gst_segment_to_stream_time),
+       (gst_segment_to_running_time):
+       The seek format can be different from the segment format when the start
+       and stop values are not to be updated, when we only do a rate change for
+       example.
+
+       * tests/check/gst/gstsegment.c: (GST_START_TEST),
+       (gst_segment_suite):
+       Add a testcase for the rate-only seeks, checking that the format is
+       correctly ignored when start and stop are not updated.
+
 2007-12-18  Sebastian Dröge  <slomo@circular-chaos.org>
 
        Patch by: Matthias Bolte <photon at mail dot upb dot de>
diff --git a/common b/common
index 67b8f4e..9707590 160000 (submodule)
--- a/common
+++ b/common
@@ -1 +1 @@
-Subproject commit 67b8f4e3c576945f4d778c9040876af3a5a0756e
+Subproject commit 970759077c95ee4e85650db023ac6f974e2aa5e1
index 5f61942..1ac8453 100644 (file)
@@ -59,15 +59,18 @@ The clock and pipeline now provides a running_time to all elements that want to
 perform synchronisation. Indeed, the running time can be observed in each
 element (during the PLAYING state) as:
   
-  running_time = absolute_time - base_time
+  C.running_time = absolute_time - base_time
+
+We note C.running_time as the running_time obtained by looking at the clock.
+This value is monotonically increasing at the rate of the clock.
 
 
 Timestamps
 ----------
  
 The GstBuffer timestamps and the preceeding NEW_SEGMENT event (See
-part-streams.txt) define a transformation of the buffers to running_time as
-follows:
+part-streams.txt) define a transformation of the buffer timestamps to
+running_time as follows:
 
 The following notation is used:
 
@@ -76,6 +79,7 @@ The following notation is used:
 
  NS:  NEWSEGMENT event preceeding the buffers.
   - NS.start: start field in the NEWSEGMENT event
+  - NS.stop: stop field in the NEWSEGMENT event
   - NS.rate: rate field of NEWSEGMENT event
   - NS.abs_rate: absolute value of rate field of NEWSEGMENT event
   - NS.time: time field in the NEWSEGMENT event
@@ -89,9 +93,12 @@ to these boundaries (see also part-segments.txt).
 The following transformation to running_time exist:
 
     if (NS.rate > 0.0)
-      running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum
+      B.running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum
     else
-      running_time = (NS.stop - B.timestamp) / NS.abs_rate + NS.accum
+      B.running_time = (NS.stop - B.timestamp) / NS.abs_rate + NS.accum
+
+We write B.running_time as the running_time obtained from the NEWSEGMENT event
+and the buffers of that segment.
 
 The first displayable buffer will yield a value of 0 (since B.timestamp ==
 NS.start and NS.accum == 0).
@@ -100,7 +107,7 @@ For NS.rate > 1.0, the timestamps will be scaled down to increase the playback
 rate. Likewise, a rate between 0.0 and 1.0 will slow down playback.
 
 For negative rates, timestamps are received stop NS.stop to NS.start so that the
-first buffer received will be transformed into running_time of 0 (B.timestamp ==
+first buffer received will be transformed into B.running_time of 0 (B.timestamp ==
 NS.stop and NS.accum == 0).
 
 
@@ -121,7 +128,7 @@ As we have seen, we can get a running_time:
 We prefix C. and B. before the two running times to note how they were
 calculated.
 
-The task of synchronized playback is to make sure that we play be buffer with
+The task of synchronized playback is to make sure that we play a buffer with
 B.running_time at the moment when the clock reaches the same C.running_time.
 
 Thus the following must hold:
@@ -162,7 +169,7 @@ between 0 and the total duration of the media file.
 It is the stream time that is used for:
 
   - report the POSITION query in the pipeline
-  - the position used in seek queries
+  - the position used in seek events/queries
   - the position used to synchronize controller values
 
 Stream time is calculated using the buffer times and the preceeding NEWSEGMENT
index 8ee6ef3..9b26e47 100644 (file)
@@ -274,15 +274,13 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
 
   if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED))
     segment->format = format;
-  else
-    g_return_if_fail (segment->format == format);
 
   update_start = update_stop = TRUE;
 
-  /* start is never invalid */
+  /* segment->start is never invalid */
   switch (start_type) {
     case GST_SEEK_TYPE_NONE:
-      /* no update to segment */
+      /* no update to segment, take previous start */
       start = segment->start;
       update_start = FALSE;
       break;
@@ -290,13 +288,17 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
       /* start holds desired position, map -1 to the start */
       if (start == -1)
         start = 0;
+      /* start must be 0 or the formats must match */
+      g_return_if_fail (start == 0 || segment->format == format);
       break;
     case GST_SEEK_TYPE_CUR:
-      /* add start to currently configure segment */
+      g_return_if_fail (start == 0 || segment->format == format);
+      /* add start to currently configured segment */
       start = segment->start + start;
       break;
     case GST_SEEK_TYPE_END:
       if (segment->duration != -1) {
+        g_return_if_fail (start == 0 || segment->format == format);
         /* add start to total length */
         start = segment->duration + start;
       } else {
@@ -319,18 +321,24 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
       update_stop = FALSE;
       break;
     case GST_SEEK_TYPE_SET:
-      /* stop holds required value */
+      /* stop holds required value, if it's not -1, it must be of the same
+       * format as the segment. */
+      g_return_if_fail (stop == -1 || segment->format == format);
       break;
     case GST_SEEK_TYPE_CUR:
-      if (segment->stop != -1)
+      if (segment->stop != -1) {
+        /* only add compatible formats or 0 */
+        g_return_if_fail (stop == 0 || segment->format == format);
         stop = segment->stop + stop;
-      else
+      else
         stop = -1;
       break;
     case GST_SEEK_TYPE_END:
-      if (segment->duration != -1)
+      if (segment->duration != -1) {
+        /* only add compatible formats or 0 */
+        g_return_if_fail (stop == 0 || segment->format == format);
         stop = segment->duration + stop;
-      else {
+      else {
         stop = segment->stop;
         update_stop = FALSE;
       }
@@ -373,8 +381,7 @@ gst_segment_set_seek (GstSegment * segment, gdouble rate,
     *update = last_stop != segment->last_stop;
 
   /* update new position */
-  if (last_stop != segment->last_stop)
-    segment->last_stop = last_stop;
+  segment->last_stop = last_stop;
 
   segment->time = start;
   segment->stop = stop;
index ba4e12e..bc3d0b6 100644 (file)
@@ -436,6 +436,137 @@ GST_START_TEST (segment_seek_reverse)
 GST_END_TEST;
 
 /* mess with the segment structure in the bytes format */
+GST_START_TEST (segment_seek_rate)
+{
+  GstSegment segment;
+  gboolean update;
+
+  gst_segment_init (&segment, GST_FORMAT_BYTES);
+
+  /* configure segment to rate 2.0, format does not matter when we don't specify
+   * a start or stop position. */
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_UNDEFINED,
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_NONE, -1, &update);
+  fail_unless (segment.format == GST_FORMAT_BYTES);
+  fail_unless (segment.start == 0);
+  fail_unless (segment.stop == -1);
+  fail_unless (segment.rate == 2.0);
+  fail_unless (update == FALSE);
+
+  /* 0 is the same in all formats and should not fail */
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_NONE, -1, &update);
+  fail_unless (segment.format == GST_FORMAT_BYTES);
+
+  /* set to -1 means start from 0 */
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_SET, -1, GST_SEEK_TYPE_NONE, -1, &update);
+  fail_unless (segment.format == GST_FORMAT_BYTES);
+  fail_unless (segment.start == 0);
+
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_CUR, 0, GST_SEEK_TYPE_NONE, -1, &update);
+
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_END, 0, GST_SEEK_TYPE_NONE, -1, &update);
+
+  /* -1 for end is fine too in all formats */
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_SET, -1, &update);
+
+  /* 0 as relative end is fine too */
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_CUR, 0, &update);
+
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 0, &update);
+
+  /* set a real stop position, this must happen in bytes */
+  gst_segment_set_seek (&segment, 3.0,
+      GST_FORMAT_BYTES,
+      GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_SET, 100, &update);
+  fail_unless (segment.format == GST_FORMAT_BYTES);
+  fail_unless (segment.start == 0);
+  fail_unless (segment.stop == 100);
+  fail_unless (segment.rate == 3.0);
+  /* no seek should happen, we just updated the stop position in forward
+   * playback mode.*/
+  fail_unless (update == FALSE);
+
+  /* 0 as relative end is fine too */
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_CUR, 0, &update);
+  fail_unless (segment.stop == 100);
+
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 0, &update);
+  fail_unless (segment.stop == 100);
+
+  /* -1 for end is fine too in all formats */
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_SET, -1, &update);
+  fail_unless (segment.stop == -1);
+
+  /* set some duration, stop -1 END seeks will now work with the
+   * duration, if the formats match */
+  gst_segment_set_duration (&segment, GST_FORMAT_BYTES, 200);
+  fail_unless (segment.duration == 200);
+
+  /* seek to end in any format with 0 should set the stop to the
+   * duration */
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_TIME, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 0, &update);
+  fail_unless (segment.stop == 200);
+  fail_unless (segment.duration == 200);
+
+  /* subtract 100 from the end */
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, -100, &update);
+  fail_unless (segment.stop == 100);
+  fail_unless (segment.duration == 200);
+
+  /* add 100 to the duration, this should be clamped to the duration */
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_NONE, -1, GST_SEEK_TYPE_END, 100, &update);
+  fail_unless (segment.stop == 200);
+  fail_unless (segment.duration == 200);
+
+  /* add 300 to the start, this should be clamped to the duration */
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_CUR, 300, GST_SEEK_TYPE_END, 0, &update);
+  fail_unless (segment.start == 200);
+  fail_unless (segment.stop == 200);
+  fail_unless (segment.duration == 200);
+
+  /* subtract 300 from the start, this should be clamped to 0 */
+  gst_segment_set_seek (&segment, 2.0,
+      GST_FORMAT_BYTES, GST_SEEK_FLAG_NONE,
+      GST_SEEK_TYPE_CUR, -300, GST_SEEK_TYPE_END, 0, &update);
+  fail_unless (segment.start == 0);
+  fail_unless (segment.stop == 200);
+  fail_unless (segment.duration == 200);
+}
+
+GST_END_TEST;
+
+/* mess with the segment structure in the bytes format */
 GST_START_TEST (segment_newsegment_open)
 {
   GstSegment segment;
@@ -1505,6 +1636,7 @@ gst_segment_suite (void)
   tcase_add_test (tc_chain, segment_seek_nosize);
   tcase_add_test (tc_chain, segment_seek_size);
   tcase_add_test (tc_chain, segment_seek_reverse);
+  tcase_add_test (tc_chain, segment_seek_rate);
   tcase_add_test (tc_chain, segment_newsegment_open);
   tcase_add_test (tc_chain, segment_newsegment_closed);
   tcase_add_test (tc_chain, segment_newsegment_streamtime);