segment: add method for converting to position

Add gst_segment_to_position() that converts a running_time to a position in the
segment. A faulty variant of this function is currently used in inputselector
but we'll need it for frame stepping too.

API: GstSegment::gst_segment_to_position()
This commit is contained in:
Wim Taymans 2009-06-03 19:06:30 +02:00
parent a907f8d145
commit 92984a116b
5 changed files with 150 additions and 9 deletions

View file

@ -1983,6 +1983,7 @@ gst_segment_set_newsegment_full
gst_segment_set_seek gst_segment_set_seek
gst_segment_to_running_time gst_segment_to_running_time
gst_segment_to_stream_time gst_segment_to_stream_time
gst_segment_to_position
<SUBSECTION Standard> <SUBSECTION Standard>
GST_TYPE_SEGMENT GST_TYPE_SEGMENT
gst_segment_get_type gst_segment_get_type

View file

@ -465,7 +465,7 @@ gst_segment_set_newsegment_full (GstSegment * segment, gboolean update,
g_return_if_fail (segment->format == format); g_return_if_fail (segment->format == format);
if (update) { if (update) {
if (segment->rate > 0.0) { if (G_LIKELY (segment->rate > 0.0)) {
/* an update to the current segment is done, elapsed time is /* an update to the current segment is done, elapsed time is
* difference between the old start and new start. */ * difference between the old start and new start. */
if (start > segment->start) if (start > segment->start)
@ -511,7 +511,7 @@ gst_segment_set_newsegment_full (GstSegment * segment, gboolean update,
last_stop = stop; last_stop = stop;
} }
/* use previous rate to calculate duration */ /* use previous rate to calculate duration */
if (segment->abs_rate != 1.0) if (G_LIKELY (segment->abs_rate != 1.0))
duration /= segment->abs_rate; duration /= segment->abs_rate;
/* accumulate duration */ /* accumulate duration */
@ -565,7 +565,7 @@ gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
/* if we have the position for the same format as the segment, we can compare /* 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 */ * the start and stop values, otherwise we assume 0 and -1 */
if (segment->format == format) { if (G_LIKELY (segment->format == format)) {
start = segment->start; start = segment->start;
stop = segment->stop; stop = segment->stop;
time = segment->time; time = segment->time;
@ -593,18 +593,18 @@ gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
abs_applied_rate = ABS (segment->applied_rate); abs_applied_rate = ABS (segment->applied_rate);
/* correct for applied rate if needed */ /* correct for applied rate if needed */
if (abs_applied_rate != 1.0) if (G_UNLIKELY (abs_applied_rate != 1.0))
result *= abs_applied_rate; result *= abs_applied_rate;
/* add or subtract from segment time based on applied rate */ /* add or subtract from segment time based on applied rate */
if (segment->applied_rate > 0.0) { if (G_LIKELY (segment->applied_rate > 0.0)) {
/* correct for segment time */ /* correct for segment time */
result += time; result += time;
} else { } else {
/* correct for segment time, clamp at 0. Streams with a negative /* correct for segment time, clamp at 0. Streams with a negative
* applied_rate have timestamps between start and stop, as usual, but have * applied_rate have timestamps between start and stop, as usual, but have
* the time member starting high and going backwards. */ * the time member starting high and going backwards. */
if (time > result) if (G_LIKELY (time > result))
result = time - result; result = time - result;
else else
result = 0; result = 0;
@ -650,7 +650,7 @@ gst_segment_to_running_time (GstSegment * segment, GstFormat format,
/* if we have the position for the same format as the segment, we can compare /* 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 */ * the start and stop values, otherwise we assume 0 and -1 */
if (segment->format == format) { if (G_LIKELY (segment->format == format)) {
start = segment->start; start = segment->start;
stop = segment->stop; stop = segment->stop;
accum = segment->accum; accum = segment->accum;
@ -664,7 +664,7 @@ gst_segment_to_running_time (GstSegment * segment, GstFormat format,
if (G_UNLIKELY (position < start)) if (G_UNLIKELY (position < start))
return -1; return -1;
if (segment->rate > 0.0) { if (G_LIKELY (segment->rate > 0.0)) {
/* outside of the segment boundary stop */ /* outside of the segment boundary stop */
if (G_UNLIKELY (stop != -1 && position > stop)) if (G_UNLIKELY (stop != -1 && position > stop))
return -1; return -1;
@ -683,7 +683,7 @@ gst_segment_to_running_time (GstSegment * segment, GstFormat format,
/* scale based on the rate, avoid division by and conversion to /* scale based on the rate, avoid division by and conversion to
* float when not needed */ * float when not needed */
if (segment->abs_rate != 1.0) if (G_UNLIKELY (segment->abs_rate != 1.0))
result /= segment->abs_rate; result /= segment->abs_rate;
/* correct for accumulated segments */ /* correct for accumulated segments */
@ -761,3 +761,73 @@ gst_segment_clip (GstSegment * segment, GstFormat format, gint64 start,
return TRUE; return TRUE;
} }
/**
* gst_segment_to_position:
* @segment: a #GstSegment structure.
* @format: the format of the segment.
* @running_time: the running_time in the segment
*
* Convert @running_time into a position in the segment so that
* gst_segment_to_running_time() with that position returns @running_time.
*
* Returns: the position in the segment for @running_time.
*
* Since: 0.10.24
*/
gint64
gst_segment_to_position (GstSegment * segment, GstFormat format,
gint64 running_time)
{
gint64 result;
gint64 start, stop, accum;
g_return_val_if_fail (segment != NULL, -1);
if (G_UNLIKELY (running_time == -1))
return -1;
if (G_UNLIKELY (segment->format == GST_FORMAT_UNDEFINED))
segment->format = format;
/* 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 (G_LIKELY (segment->format == format)) {
start = segment->start;
stop = segment->stop;
accum = segment->accum;
} else {
start = 0;
stop = -1;
accum = 0;
}
/* this running_time was for a previous segment */
if (running_time < accum)
return -1;
/* start by subtracting the accumulated time */
result = running_time - accum;
/* move into the segment at the right rate */
if (G_UNLIKELY (segment->abs_rate != 1.0))
result *= segment->abs_rate;
if (G_LIKELY (segment->rate > 0.0)) {
/* bring to corrected position in segment */
result += start;
/* outside of the segment boundary stop */
if (G_UNLIKELY (stop != -1 && result > stop))
return -1;
} else {
/* cannot continue if no stop position set or outside of
* the segment. */
if (G_UNLIKELY (stop == -1 || result + start > stop))
return -1;
/* bring to corrected position in segment */
result = stop - result;
}
return result;
}

View file

@ -96,6 +96,7 @@ void gst_segment_set_newsegment_full (GstSegment *segment, gboolean upda
gint64 gst_segment_to_stream_time (GstSegment *segment, GstFormat format, gint64 position); gint64 gst_segment_to_stream_time (GstSegment *segment, GstFormat format, gint64 position);
gint64 gst_segment_to_running_time (GstSegment *segment, GstFormat format, gint64 position); gint64 gst_segment_to_running_time (GstSegment *segment, GstFormat format, gint64 position);
gint64 gst_segment_to_position (GstSegment *segment, GstFormat format, gint64 running_time);
gboolean gst_segment_clip (GstSegment *segment, GstFormat format, gint64 start, gboolean gst_segment_clip (GstSegment *segment, GstFormat format, gint64 start,
gint64 stop, gint64 *clip_start, gint64 *clip_stop); gint64 stop, gint64 *clip_start, gint64 *clip_stop);

View file

@ -1341,17 +1341,25 @@ GST_START_TEST (segment_newsegment_runningtime)
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 0); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 0);
fail_unless (result == 0); fail_unless (result == 0);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 0);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100);
fail_unless (result == 100); fail_unless (result == 100);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 100);
/* at edge is exactly the segment duration */ /* at edge is exactly the segment duration */
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 200); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 200);
fail_unless (result == 200); fail_unless (result == 200);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 200);
/* outside of the segment */ /* outside of the segment */
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 300); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 300);
fail_unless (result == -1); fail_unless (result == -1);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, 300);
fail_unless (result == -1);
/*********************************************************** /***********************************************************
* time shifted by 500, check if accumulation worked. * time shifted by 500, check if accumulation worked.
@ -1371,13 +1379,19 @@ GST_START_TEST (segment_newsegment_runningtime)
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 0); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 0);
fail_unless (result == 200); fail_unless (result == 200);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 0);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100);
fail_unless (result == 250); fail_unless (result == 250);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 100);
/* outside of the segment */ /* outside of the segment */
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500);
fail_unless (result == -1); fail_unless (result == -1);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, 310);
fail_unless (result == -1);
/******************************************** /********************************************
* time offset by 500 * time offset by 500
@ -1397,19 +1411,29 @@ GST_START_TEST (segment_newsegment_runningtime)
/* before segment is invalid */ /* before segment is invalid */
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 400); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 400);
fail_unless (result == -1); fail_unless (result == -1);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, 200);
fail_unless (result == -1);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500);
fail_unless (result == 300); fail_unless (result == 300);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 500);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 600); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 600);
fail_unless (result == 400); fail_unless (result == 400);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 600);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 700); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 700);
fail_unless (result == 500); fail_unless (result == 500);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 700);
/* outside of the segment */ /* outside of the segment */
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 800); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 800);
fail_unless (result == -1); fail_unless (result == -1);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, 600);
fail_unless (result == -1);
/********************************************************** /**********************************************************
* time offset by 500, shifted by 200 * time offset by 500, shifted by 200
@ -1429,19 +1453,29 @@ GST_START_TEST (segment_newsegment_runningtime)
/* before segment is invalid */ /* before segment is invalid */
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 400); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 400);
fail_unless (result == -1); fail_unless (result == -1);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, 400);
fail_unless (result == -1);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500);
fail_unless (result == 700); fail_unless (result == 700);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 500);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 600); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 600);
fail_unless (result == 600); fail_unless (result == 600);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 600);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 700); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 700);
fail_unless (result == 500); fail_unless (result == 500);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 700);
/* outside of the segment */ /* outside of the segment */
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 800); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 800);
fail_unless (result == -1); fail_unless (result == -1);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, 800);
fail_unless (result == -1);
/********************************************************** /**********************************************************
* time offset by 500, shifted by 200 * time offset by 500, shifted by 200
@ -1461,20 +1495,30 @@ GST_START_TEST (segment_newsegment_runningtime)
/* before segment is invalid */ /* before segment is invalid */
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 400); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 400);
fail_unless (result == -1); fail_unless (result == -1);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, 600);
fail_unless (result == -1);
/* total scaled segment time is 100, accum is 700, so we get 800 */ /* total scaled segment time is 100, accum is 700, so we get 800 */
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500);
fail_unless (result == 800); fail_unless (result == 800);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 500);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 600); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 600);
fail_unless (result == 750); fail_unless (result == 750);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 600);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 700); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 700);
fail_unless (result == 700); fail_unless (result == 700);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 700);
/* outside of the segment */ /* outside of the segment */
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 800); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 800);
fail_unless (result == -1); fail_unless (result == -1);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, 900);
fail_unless (result == -1);
/* see if negative rate closed segment correctly */ /* see if negative rate closed segment correctly */
gst_segment_set_newsegment_full (&segment, FALSE, -2.0, -1.0, gst_segment_set_newsegment_full (&segment, FALSE, -2.0, -1.0,
@ -1482,6 +1526,8 @@ GST_START_TEST (segment_newsegment_runningtime)
/* previous segment lasted 100, and was at 700 so we should get 800 */ /* previous segment lasted 100, and was at 700 so we should get 800 */
fail_unless (segment.accum == 800); fail_unless (segment.accum == 800);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, 800);
fail_unless (result == 700);
} }
GST_END_TEST; GST_END_TEST;
@ -1517,9 +1563,13 @@ GST_START_TEST (segment_newsegment_accum)
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 200); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 200);
fail_unless (result == 0); fail_unless (result == 0);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 200);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150);
fail_unless (result == 50); fail_unless (result == 50);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 150);
/* update segment, this accumulates 50 from the previous segment. */ /* update segment, this accumulates 50 from the previous segment. */
gst_segment_set_newsegment_full (&segment, TRUE, -2.0, 1.0, gst_segment_set_newsegment_full (&segment, TRUE, -2.0, 1.0,
@ -1538,10 +1588,14 @@ GST_START_TEST (segment_newsegment_accum)
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150);
fail_unless (result == 50); fail_unless (result == 50);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 150);
/* 50 accumulated + 50 / 2 */ /* 50 accumulated + 50 / 2 */
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100);
fail_unless (result == 75); fail_unless (result == 75);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 100);
/* update segment, this does not accumulate anything. */ /* update segment, this does not accumulate anything. */
gst_segment_set_newsegment_full (&segment, TRUE, 1.0, 1.0, gst_segment_set_newsegment_full (&segment, TRUE, 1.0, 1.0,
@ -1560,9 +1614,13 @@ GST_START_TEST (segment_newsegment_accum)
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100);
fail_unless (result == 50); fail_unless (result == 50);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 100);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150);
fail_unless (result == 100); fail_unless (result == 100);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 150);
} }
GST_END_TEST; GST_END_TEST;
@ -1595,12 +1653,18 @@ GST_START_TEST (segment_newsegment_accum2)
/* invalid time gives invalid result */ /* invalid time gives invalid result */
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
fail_unless (result == -1); fail_unless (result == -1);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == -1);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 200); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 200);
fail_unless (result == 0); fail_unless (result == 0);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 200);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150);
fail_unless (result == 50); fail_unless (result == 50);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 150);
/* close segment, this accumulates nothing. */ /* close segment, this accumulates nothing. */
gst_segment_set_newsegment_full (&segment, TRUE, -1.0, 1.0, gst_segment_set_newsegment_full (&segment, TRUE, -1.0, 1.0,
@ -1638,9 +1702,13 @@ GST_START_TEST (segment_newsegment_accum2)
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 150);
fail_unless (result == 50); fail_unless (result == 50);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 150);
result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 200); result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 200);
fail_unless (result == 100); fail_unless (result == 100);
result = gst_segment_to_position (&segment, GST_FORMAT_TIME, result);
fail_unless (result == 200);
} }
GST_END_TEST; GST_END_TEST;

View file

@ -836,6 +836,7 @@ EXPORTS
gst_segment_set_newsegment gst_segment_set_newsegment
gst_segment_set_newsegment_full gst_segment_set_newsegment_full
gst_segment_set_seek gst_segment_set_seek
gst_segment_to_position
gst_segment_to_running_time gst_segment_to_running_time
gst_segment_to_stream_time gst_segment_to_stream_time
gst_segtrap_is_enabled gst_segtrap_is_enabled