segment: add offset field

Add an offset field that is used to track at what position the segment was
updated. This is used to set the running time to 0 when we do a flushing
seek that doesn't update the position.

See https://bugzilla.gnome.org/show_bug.cgi?id=680306
This commit is contained in:
Wim Taymans 2012-07-27 17:09:45 +02:00
parent f05b0e222f
commit c8840b8270
3 changed files with 98 additions and 7 deletions

View file

@ -174,6 +174,7 @@ gst_segment_init (GstSegment * segment, GstFormat format)
segment->applied_rate = 1.0;
segment->format = format;
segment->base = 0;
segment->offset = 0;
segment->start = 0;
segment->stop = -1;
segment->time = 0;
@ -308,6 +309,7 @@ gst_segment_do_seek (GstSegment * segment, gdouble rate,
/* flush resets the running_time */
base = 0;
} else {
/* remember the elapsed time */
base = gst_segment_to_running_time (segment, format, position);
}
@ -324,14 +326,12 @@ gst_segment_do_seek (GstSegment * segment, gdouble rate,
position = 0;
}
}
/* set update arg to reflect update of position */
if (update)
*update = position != segment->position;
/* update new values */
segment->rate = rate;
segment->applied_rate = 1.0;
segment->base = base;
/* be explicit about our GstSeekFlag -> GstSegmentFlag conversion */
segment->flags = GST_SEGMENT_FLAG_NONE;
if ((flags & GST_SEEK_FLAG_FLUSH) != 0)
@ -340,6 +340,22 @@ gst_segment_do_seek (GstSegment * segment, gdouble rate,
segment->flags |= GST_SEGMENT_FLAG_SKIP;
if ((flags & GST_SEEK_FLAG_SEGMENT) != 0)
segment->flags |= GST_SEGMENT_FLAG_SEGMENT;
segment->rate = rate;
segment->applied_rate = 1.0;
segment->base = base;
if (rate > 0.0)
segment->offset = position - start;
else {
if (stop != -1)
segment->offset = stop - position;
else if (segment->duration != -1)
segment->offset = segment->duration - position;
else
segment->offset = 0;
}
segment->start = start;
segment->stop = stop;
segment->time = start;
@ -461,6 +477,9 @@ gst_segment_to_running_time (const GstSegment * segment, GstFormat format,
start = segment->start;
if (segment->rate > 0.0)
start += segment->offset;
/* before the segment boundary */
if (G_UNLIKELY (position < start))
return -1;
@ -477,7 +496,11 @@ gst_segment_to_running_time (const GstSegment * segment, GstFormat format,
} else {
/* cannot continue if no stop position set or outside of
* the segment. */
if (G_UNLIKELY (stop == -1 || position > stop))
if (G_UNLIKELY (stop == -1))
return -1;
stop -= segment->offset;
if (G_UNLIKELY (position > stop))
return -1;
/* bring to uncorrected position in segment */

View file

@ -144,7 +144,8 @@ typedef enum {
* @rate: the rate of the segment
* @applied_rate: the already applied rate to the segment
* @format: the format of the segment values
* @base: the base time of the segment
* @base: the base of the segment
* @offset: the offset to apply to @start or @stop
* @start: the start of the segment
* @stop: the stop of the segment
* @time: the stream time of the segment
@ -163,6 +164,7 @@ struct _GstSegment {
GstFormat format;
guint64 base;
guint64 offset;
guint64 start;
guint64 stop;
guint64 time;

View file

@ -31,8 +31,8 @@ check_times (GstSegment * segment, guint64 position, guint64 stream_time,
st = gst_segment_to_stream_time (segment, segment->format, position);
rt = gst_segment_to_running_time (segment, segment->format, position);
fail_unless (st == stream_time);
fail_unless (rt == running_time);
fail_unless_equals_int64 (st, stream_time);
fail_unless_equals_int64 (rt, running_time);
}
/* mess with the segment structure in the bytes format */
@ -138,8 +138,10 @@ GST_START_TEST (segment_seek_nosize)
fail_unless (segment.start == 200);
fail_unless (segment.position == 200);
fail_unless (segment.stop == 300);
fail_unless (segment.base == 50);
fail_unless (update == TRUE);
check_times (&segment, 200, 200, 50);
check_times (&segment, 250, 250, 100);
update = FALSE;
/* add 100 to start (to 300), set stop to 200, this is not allowed.
@ -152,8 +154,10 @@ GST_START_TEST (segment_seek_nosize)
fail_unless (segment.start == 200);
fail_unless (segment.position == 200);
fail_unless (segment.stop == 300);
fail_unless (segment.base == 50);
/* update didn't change */
fail_unless (update == FALSE);
check_times (&segment, 200, 200, 50);
check_times (&segment, 250, 250, 100);
update = TRUE;
@ -166,6 +170,7 @@ GST_START_TEST (segment_seek_nosize)
fail_unless (segment.start == 200);
fail_unless (segment.position == 200);
fail_unless (segment.stop == 300);
fail_unless (segment.base == 50);
fail_unless (update == FALSE);
check_times (&segment, 250, 250, 100);
@ -477,9 +482,11 @@ GST_START_TEST (segment_seek_rate)
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.position == 0);
fail_unless (segment.stop == -1);
fail_unless (segment.rate == 2.0);
fail_unless (update == FALSE);
check_times (&segment, 50, 50, 25);
/* set a real stop position, this must happen in bytes */
gst_segment_do_seek (&segment, 3.0,
@ -493,6 +500,7 @@ GST_START_TEST (segment_seek_rate)
/* no seek should happen, we just updated the stop position in forward
* playback mode.*/
fail_unless (update == FALSE);
check_times (&segment, 60, 60, 20);
/* set some duration, stop -1 END seeks will now work with the
* duration, if the formats match */
@ -549,6 +557,63 @@ GST_START_TEST (segment_copy)
GST_END_TEST;
/* mess with the segment structure in the bytes format */
GST_START_TEST (segment_seek_noupdate)
{
GstSegment segment;
gboolean update;
gst_segment_init (&segment, GST_FORMAT_TIME);
segment.start = 0;
segment.position = 50;
segment.stop = 200;
segment.time = 0;
/* doesn't change anything */
gst_segment_do_seek (&segment, 1.0,
GST_FORMAT_TIME,
GST_SEEK_FLAG_NONE,
GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update);
fail_unless (update == FALSE);
fail_unless (segment.format == GST_FORMAT_TIME);
fail_unless (segment.start == 0);
fail_unless (segment.stop == 200);
fail_unless (segment.time == 0);
fail_unless (segment.position == 50);
fail_unless (segment.base == 50);
fail_unless (segment.offset == 50);
gst_segment_do_seek (&segment, 2.0,
GST_FORMAT_TIME,
GST_SEEK_FLAG_NONE,
GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update);
fail_unless (update == FALSE);
fail_unless (segment.format == GST_FORMAT_TIME);
fail_unless (segment.start == 0);
fail_unless (segment.stop == 200);
fail_unless (segment.time == 0);
fail_unless (segment.position == 50);
fail_unless (segment.base == 50);
fail_unless_equals_int (segment.offset, 50);
gst_segment_do_seek (&segment, 1.0,
GST_FORMAT_TIME,
GST_SEEK_FLAG_FLUSH,
GST_SEEK_TYPE_NONE, 0, GST_SEEK_TYPE_NONE, 0, &update);
fail_unless (update == FALSE);
fail_unless (segment.format == GST_FORMAT_TIME);
fail_unless (segment.start == 0);
fail_unless (segment.stop == 200);
fail_unless (segment.time == 0);
fail_unless (segment.position == 50);
fail_unless (segment.base == 0);
fail_unless (segment.offset == 50);
}
GST_END_TEST;
static Suite *
gst_segment_suite (void)
{
@ -563,6 +628,7 @@ gst_segment_suite (void)
tcase_add_test (tc_chain, segment_seek_reverse);
tcase_add_test (tc_chain, segment_seek_rate);
tcase_add_test (tc_chain, segment_copy);
tcase_add_test (tc_chain, segment_seek_noupdate);
return s;
}