g_return_if_fail (segment->format == format);
if (update) {
- /* an update to the current segment is done, elapsed time is
- * difference between the old start and new start. */
- if (start > segment->start)
- duration = start - segment->start;
- else
- duration = 0;
+ if (segment->rate > 0.0) {
+ /* an update to the current segment is done, elapsed time is
+ * difference between the old start and new start. */
+ if (start > segment->start)
+ duration = start - segment->start;
+ else
+ duration = 0;
+ } else {
+ /* for negative rates, the elapsed duration is the diff between the stop
+ * positions */
+ if (stop != -1 && stop < segment->stop)
+ duration = segment->stop - stop;
+ else
+ duration = 0;
+ }
} else {
/* the new segment has to be aligned with the old segment.
* We first update the accumulated time of the previous
gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
gint64 position)
{
- gint64 result;
+ gint64 result, start, stop, time;
gdouble abs_applied_rate;
g_return_val_if_fail (segment != NULL, -1);
if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED))
segment->format = format;
- else
- g_return_val_if_fail (segment->format == format, -1);
+
+ /* if we have the position for the same format as the segment, we can compare
+ * the start and stop values, otherwise we assume 0 and -1 */
+ if (segment->format == format) {
+ start = segment->start;
+ stop = segment->stop;
+ time = segment->time;
+ } else {
+ start = 0;
+ stop = -1;
+ time = 0;
+ }
/* outside of the segment boundary stop */
- if (G_UNLIKELY (segment->stop != -1 && position > segment->stop))
+ if (G_UNLIKELY (stop != -1 && position > stop))
return -1;
/* before the segment boundary */
- if (G_UNLIKELY (position < segment->start))
+ if (G_UNLIKELY (position < start))
return -1;
/* time must be known */
- if (G_UNLIKELY (segment->time == -1))
+ if (G_UNLIKELY (time == -1))
return -1;
/* bring to uncorrected position in segment */
- result = position - segment->start;
+ result = position - start;
abs_applied_rate = ABS (segment->applied_rate);
/* add or subtract from segment time based on applied rate */
if (segment->applied_rate > 0.0) {
/* correct for segment time */
- result += segment->time;
+ result += time;
} else {
/* correct for segment time, clamp at 0 */
- if (segment->time > result)
- result = segment->time - result;
+ if (time > result)
+ result = time - result;
else
result = 0;
}
gint64 position)
{
gint64 result;
+ gint64 start, stop, accum;
g_return_val_if_fail (segment != NULL, -1);
if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED))
segment->format = format;
- else if (segment->accum)
- g_return_val_if_fail (segment->format == format, -1);
+
+ /* if we have the position for the same format as the segment, we can compare
+ * the start and stop values, otherwise we assume 0 and -1 */
+ if (segment->format == format) {
+ start = segment->start;
+ stop = segment->stop;
+ accum = segment->accum;
+ } else {
+ start = 0;
+ stop = -1;
+ accum = 0;
+ }
/* before the segment boundary */
- if (G_UNLIKELY (position < segment->start))
+ if (G_UNLIKELY (position < start))
return -1;
if (segment->rate > 0.0) {
/* outside of the segment boundary stop */
- if (G_UNLIKELY (segment->stop != -1 && position > segment->stop))
+ if (G_UNLIKELY (stop != -1 && position > stop))
return -1;
/* bring to uncorrected position in segment */
- result = position - segment->start;
+ result = position - start;
} else {
/* cannot continue if no stop position set or outside of
* the segment. */
- if (G_UNLIKELY (segment->stop == -1 || position > segment->stop))
+ if (G_UNLIKELY (stop == -1 || position > stop))
return -1;
/* bring to uncorrected position in segment */
- result = segment->stop - position;
+ result = stop - position;
}
/* scale based on the rate, avoid division by and conversion to
result /= segment->abs_rate;
/* correct for accumulated segments */
- result += segment->accum;
+ result += accum;
return result;
}
GST_END_TEST;
+/* mess with the segment structure in the time format */
+GST_START_TEST (segment_newsegment_accum)
+{
+ GstSegment segment;
+ gint64 result;
+
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+
+ /***************************
+ * Normal reverse segment
+ ***************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 1.0,
+ GST_FORMAT_TIME, 0, 200, 0);
+
+ fail_unless (segment.rate == -1.0);
+ fail_unless (segment.applied_rate == 1.0);
+ fail_unless (segment.format == GST_FORMAT_TIME);
+ fail_unless (segment.flags == 0);
+ fail_unless (segment.start == 0);
+ fail_unless (segment.stop == 200);
+ fail_unless (segment.time == 0);
+ fail_unless (segment.accum == 0);
+ fail_unless (segment.last_stop == 0);
+ fail_unless (segment.duration == -1);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == 0);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150);
+ fail_unless (result == 50);
+
+ /* update segment, this accumulates 50 from the previous segment. */
+ gst_segment_set_newsegment_full (&segment, TRUE, -2.0, 1.0,
+ GST_FORMAT_TIME, 0, 150, 0);
+
+ fail_unless (segment.rate == -2.0);
+ fail_unless (segment.applied_rate == 1.0);
+ fail_unless (segment.format == GST_FORMAT_TIME);
+ fail_unless (segment.flags == 0);
+ fail_unless (segment.start == 0);
+ fail_unless (segment.stop == 150);
+ fail_unless (segment.time == 0);
+ fail_unless (segment.accum == 50);
+ fail_unless (segment.last_stop == 0);
+ fail_unless (segment.duration == -1);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150);
+ fail_unless (result == 50);
+
+ /* 50 accumulated + 50 / 2 */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 75);
+
+ /* update segment, this does not accumulate anything. */
+ gst_segment_set_newsegment_full (&segment, TRUE, 1.0, 1.0,
+ GST_FORMAT_TIME, 100, 200, 100);
+
+ fail_unless (segment.rate == 1.0);
+ fail_unless (segment.applied_rate == 1.0);
+ fail_unless (segment.format == GST_FORMAT_TIME);
+ fail_unless (segment.flags == 0);
+ fail_unless (segment.start == 100);
+ fail_unless (segment.stop == 200);
+ fail_unless (segment.time == 100);
+ fail_unless (segment.accum == 50);
+ fail_unless (segment.last_stop == 100);
+ fail_unless (segment.duration == -1);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 50);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150);
+ fail_unless (result == 100);
+}
+
+GST_END_TEST;
+
+/* mess with the segment structure in the time format */
+GST_START_TEST (segment_newsegment_accum2)
+{
+ GstSegment segment;
+ gint64 result;
+
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+
+ /***************************
+ * Normal reverse segment
+ ***************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 1.0,
+ GST_FORMAT_TIME, 0, 200, 0);
+
+ fail_unless (segment.rate == -1.0);
+ fail_unless (segment.applied_rate == 1.0);
+ fail_unless (segment.format == GST_FORMAT_TIME);
+ fail_unless (segment.flags == 0);
+ fail_unless (segment.start == 0);
+ fail_unless (segment.stop == 200);
+ fail_unless (segment.time == 0);
+ fail_unless (segment.accum == 0);
+ fail_unless (segment.last_stop == 0);
+ fail_unless (segment.duration == -1);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == 0);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150);
+ fail_unless (result == 50);
+
+ /* close segment, this accumulates nothing. */
+ gst_segment_set_newsegment_full (&segment, TRUE, -1.0, 1.0,
+ GST_FORMAT_TIME, 150, 200, 0);
+
+ fail_unless (segment.rate == -1.0);
+ fail_unless (segment.applied_rate == 1.0);
+ fail_unless (segment.format == GST_FORMAT_TIME);
+ fail_unless (segment.flags == 0);
+ fail_unless (segment.start == 150);
+ fail_unless (segment.stop == 200);
+ fail_unless (segment.time == 0);
+ fail_unless (segment.accum == 0);
+ fail_unless (segment.last_stop == 150);
+ fail_unless (segment.duration == -1);
+
+ /* new segment, this accumulates 50. */
+ gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
+ GST_FORMAT_TIME, 150, 300, 150);
+
+ fail_unless (segment.rate == 1.0);
+ fail_unless (segment.applied_rate == 1.0);
+ fail_unless (segment.format == GST_FORMAT_TIME);
+ fail_unless (segment.flags == 0);
+ fail_unless (segment.start == 150);
+ fail_unless (segment.stop == 300);
+ fail_unless (segment.time == 150);
+ fail_unless (segment.accum == 50);
+ fail_unless (segment.last_stop == 150);
+ fail_unless (segment.duration == -1);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150);
+ fail_unless (result == 50);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == 100);
+}
+
+GST_END_TEST;
+
Suite *
gst_segment_suite (void)
{
tcase_add_test (tc_chain, segment_newsegment_streamtime_applied_rate);
tcase_add_test (tc_chain, segment_newsegment_streamtime_applied_rate_rate);
tcase_add_test (tc_chain, segment_newsegment_runningtime);
+ tcase_add_test (tc_chain, segment_newsegment_accum);
+ tcase_add_test (tc_chain, segment_newsegment_accum2);
return s;
}