* @stop: the stop value of the segment
* @position: stream position
*
- * Allocate a new newsegment event with the given format/values tripplets.
+ * Allocate a new newsegment event with the given format/values tripplets
+ *
+ * This method calls gst_event_new_new_segment_full() passing a default
+ * value of 1.0 for applied_rate
+ */
+GstEvent *
+gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
+ gint64 start, gint64 stop, gint64 position)
+{
+ return gst_event_new_new_segment_full (update, rate, 1.0, format, start,
+ stop, position);
+}
+
+/**
+ * gst_event_parse_new_segment:
+ * @event: The event to query
+ * @update: A pointer to the update flag of the segment
+ * @rate: A pointer to the rate of the segment
+ * @format: A pointer to the format of the newsegment values
+ * @start: A pointer to store the start value in
+ * @stop: A pointer to store the stop value in
+ * @position: A pointer to store the stream time in
+ *
+ * Get the update flag, rate, format, start, stop and position in the
+ * newsegment event. In general, gst_event_parse_new_segment_full() should
+ * be used instead of this, to also retrieve the applied_rate value of the
+ * segment. See gst_event_new_new_segment_full() for a full description
+ * of the newsegment event.
+ */
+void
+gst_event_parse_new_segment (GstEvent * event, gboolean * update,
+ gdouble * rate, GstFormat * format, gint64 * start,
+ gint64 * stop, gint64 * position)
+{
+ gst_event_parse_new_segment_full (event, update, rate, NULL, format, start,
+ stop, position);
+}
+
+/**
+ * gst_event_new_new_segment_full:
+ * @update: Whether this segment is an update to a previous one
+ * @rate: A new rate for playback
+ * @applied_rate: The rate factor which has already been applied
+ * @format: The format of the segment values
+ * @start: The start value of the segment
+ * @stop: The stop value of the segment
+ * @position: stream position
+ *
+ * Allocate a new newsegment event with the given format/values triplets.
*
* The newsegment event marks the range of buffers to be processed. All
* data not within the segment range is not to be processed. This can be
- * used intelligently by plugins to use more efficient methods of skipping
+ * used intelligently by plugins to apply more efficient methods of skipping
* unneeded packets.
*
- * The stream time of the segment is used to convert the buffer timestamps
- * into the stream time again, this is usually done in sinks to report the
- * current stream_time. @stream_time cannot be -1.
+ * The position value of the segment is used in conjunction with the start
+ * value to convert the buffer timestamps into the stream time. This is
+ * usually done in sinks to report the current stream_time.
+ * @position represents the stream_time of a buffer carrying a timestamp of
+ * @start. @position cannot be -1.
*
* @start cannot be -1, @stop can be -1. If there
- * is a valid @stop given, it must be greater or equal than @start.
+ * is a valid @stop given, it must be greater or equal the @start, including
+ * when the indicated playback @rate is < 0
+ *
+ * The @applied_rate value provides information about any rate adjustment that
+ * has already been made to the timestamps and content on the buffers of the
+ * stream. (@rate * @applied_rate) should always equal the rate that has been
+ * requested for playback. For example, if an element has an input segment
+ * with intended playback @rate of 2.0 and applied_rate of 1.0, it can adjust
+ * incoming timestamps and buffer content by half and output a newsegment event
+ * with @rate of 1.0 and @applied_rate of 2.0
*
* After a newsegment event, the buffer stream time is calculated with:
*
- * stream_time + (TIMESTAMP(buf) - start) * ABS (rate)
+ * position + (TIMESTAMP(buf) - start) * ABS (rate * applied_rate)
*
* Returns: A new newsegment event.
+ *
+ * Since: 0.10.6
*/
GstEvent *
-gst_event_new_new_segment (gboolean update, gdouble rate, GstFormat format,
- gint64 start, gint64 stop, gint64 position)
+gst_event_new_new_segment_full (gboolean update, gdouble rate,
+ gdouble applied_rate, GstFormat format, gint64 start, gint64 stop,
+ gint64 position)
{
g_return_val_if_fail (rate != 0.0, NULL);
+ g_return_val_if_fail (applied_rate != 0.0, NULL);
if (format == GST_FORMAT_TIME) {
GST_CAT_INFO (GST_CAT_EVENT,
"start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", position %"
G_GINT64_FORMAT, update, rate, format, start, stop, position);
}
+
g_return_val_if_fail (position != -1, NULL);
g_return_val_if_fail (start != -1, NULL);
if (stop != -1)
gst_structure_new ("GstEventNewsegment",
"update", G_TYPE_BOOLEAN, update,
"rate", G_TYPE_DOUBLE, rate,
+ "applied_rate", G_TYPE_DOUBLE, applied_rate,
"format", GST_TYPE_FORMAT, format,
"start", G_TYPE_INT64, start,
"stop", G_TYPE_INT64, stop,
}
/**
- * gst_event_parse_new_segment:
+ * gst_event_parse_new_segment_full:
* @event: The event to query
* @update: A pointer to the update flag of the segment
* @rate: A pointer to the rate of the segment
+ * @applied_rate: A pointer to the applied_rate of the segment
* @format: A pointer to the format of the newsegment values
* @start: A pointer to store the start value in
* @stop: A pointer to store the stop value in
* @position: A pointer to store the stream time in
*
- * Get the format, start, stop and position in the newsegment event.
+ * Get the update, rate, applied_rate, format, start, stop and
+ * position in the newsegment event. See gst_event_new_new_segment_full()
+ * for a full description of the newsegment event.
+ *
+ * Since: 0.10.6
*/
void
-gst_event_parse_new_segment (GstEvent * event, gboolean * update,
- gdouble * rate, GstFormat * format, gint64 * start,
- gint64 * stop, gint64 * position)
+gst_event_parse_new_segment_full (GstEvent * event, gboolean * update,
+ gdouble * rate, gdouble * applied_rate, GstFormat * format,
+ gint64 * start, gint64 * stop, gint64 * position)
{
const GstStructure *structure;
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT);
structure = gst_event_get_structure (event);
- if (update)
+ if (G_LIKELY (update))
*update =
g_value_get_boolean (gst_structure_get_value (structure, "update"));
- if (rate)
+ if (G_LIKELY (rate))
*rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
- if (format)
+ if (G_LIKELY (applied_rate))
+ *applied_rate =
+ g_value_get_double (gst_structure_get_value (structure,
+ "applied_rate"));
+ if (G_LIKELY (format))
*format = g_value_get_enum (gst_structure_get_value (structure, "format"));
- if (start)
+ if (G_LIKELY (start))
*start = g_value_get_int64 (gst_structure_get_value (structure, "start"));
- if (stop)
+ if (G_LIKELY (stop))
*stop = g_value_get_int64 (gst_structure_get_value (structure, "stop"));
- if (position)
+ if (G_LIKELY (position))
*position =
g_value_get_int64 (gst_structure_get_value (structure, "position"));
}
gst_event_new_tag (GstTagList * taglist)
{
g_return_val_if_fail (taglist != NULL, NULL);
-
return gst_event_new_custom (GST_EVENT_TAG, (GstStructure *) taglist);
}
{
g_return_if_fail (GST_IS_EVENT (event));
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_TAG);
-
if (taglist)
*taglist = (GstTagList *) event->structure;
}
"creating buffersize format %d, minsize %" G_GINT64_FORMAT
", maxsize %" G_GINT64_FORMAT ", async %d", format,
minsize, maxsize, async);
-
return gst_event_new_custom (GST_EVENT_BUFFERSIZE,
gst_structure_new ("GstEventBufferSize",
"format", GST_TYPE_FORMAT, format,
g_return_if_fail (GST_IS_EVENT (event));
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_BUFFERSIZE);
-
structure = gst_event_get_structure (event);
if (format)
*format = g_value_get_enum (gst_structure_get_value (structure, "format"));
GstClockTime timestamp)
{
GST_CAT_INFO (GST_CAT_EVENT,
- "creating qos proportion %lf, diff %" GST_TIME_FORMAT
+ "creating qos proportion %lf, diff %" G_GINT64_FORMAT
", timestamp %" GST_TIME_FORMAT, proportion,
- GST_TIME_ARGS (diff), GST_TIME_ARGS (timestamp));
+ diff, GST_TIME_ARGS (timestamp));
return gst_event_new_custom (GST_EVENT_QOS,
gst_structure_new ("GstEventQOS",
g_return_if_fail (GST_IS_EVENT (event));
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_QOS);
-
structure = gst_event_get_structure (event);
if (proportion)
*proportion =
* Parses a seek @event and stores the results in the given result locations.
*/
void
-gst_event_parse_seek (GstEvent * event, gdouble * rate, GstFormat * format,
- GstSeekFlags * flags,
- GstSeekType * cur_type, gint64 * cur,
- GstSeekType * stop_type, gint64 * stop)
+gst_event_parse_seek (GstEvent * event, gdouble * rate,
+ GstFormat * format, GstSeekFlags * flags, GstSeekType * cur_type,
+ gint64 * cur, GstSeekType * stop_type, gint64 * stop)
{
const GstStructure *structure;
g_return_if_fail (GST_IS_EVENT (event));
g_return_if_fail (GST_EVENT_TYPE (event) == GST_EVENT_SEEK);
-
structure = gst_event_get_structure (event);
if (rate)
*rate = g_value_get_double (gst_structure_get_value (structure, "rate"));
gst_event_new_navigation (GstStructure * structure)
{
g_return_val_if_fail (structure != NULL, NULL);
-
return gst_event_new_custom (GST_EVENT_NAVIGATION, structure);
}
* A segment structure is initialized with gst_segment_init(), which takes a #GstFormat
* that will be used as the format of the segment values. The segment will be configured
* with a start value of 0 and a stop/duration of -1, which is undefined. The default
- * rate is 1.0.
+ * rate and applied_rate is 1.0.
*
* If the segment is used for managing seeks, the segment duration should be set with
* gst_segment_set_duration(). The public duration field contains the duration of the
- * segment.
+ * segment. When using the segment for seeking, the start and time members should
+ * normally be left to their default 0 value. The stop position is left to -1 unless
+ * explicitly configured to a different value after a seek event.
*
* The current position in the segment should be set with the gst_segment_set_last_stop().
* The public last_stop field contains the last set stop position in the segment.
*
* For elements that want to synchronize to the pipeline clock, gst_segment_to_running_time()
* can be used to convert a timestamp to a value that can be used to synchronize
- * to the clock. This function takes into account all accumulated segments.
+ * to the clock. This function takes into account all accumulated segments as well as
+ * any rate or applied_rate conversions.
*
* For elements that need to perform operations on media data in stream_time,
* gst_segment_to_stream_time() can be used to convert a timestamp and the segment
* info to stream time (which is always between 0 and the duration of the stream).
*
- * Last reviewed on 2006-03-12 (0.10.5)
+ * Last reviewed on 2006-05-03 (0.10.6)
*/
static GstSegment *
segment->rate = 1.0;
segment->abs_rate = 1.0;
+ segment->applied_rate = 1.0;
segment->format = format;
segment->flags = 0;
segment->start = 0;
* from GST_SEEK_TYPE_NONE, the current position is not updated and
* streaming should continue from the last position, possibly with
* updated rate, flags or stop position.
+ *
+ * The applied rate of the segment will be set to 1.0 by default.
+ * If the caller can apply a rate change, it should update @segment
+ * rate and applied_rate after calling this function.
*/
void
gst_segment_set_seek (GstSegment * segment, gdouble rate,
segment->rate = rate;
segment->abs_rate = ABS (rate);
+ segment->applied_rate = 1.0;
segment->flags = flags;
segment->start = cur;
if (update_start) {
* @stop: the new stop value
* @time: the new stream time
*
- * Update the segment structure with the field values of a new segment event.
+ * Update the segment structure with the field values of a new segment event and
+ * with a default applied_rate of 1.0.
+ *
+ * Since: 0.10.6
*/
void
gst_segment_set_newsegment (GstSegment * segment, gboolean update, gdouble rate,
GstFormat format, gint64 start, gint64 stop, gint64 time)
{
+ gst_segment_set_newsegment_full (segment, update, rate, 1.0, format, start,
+ stop, time);
+}
+
+/**
+ * gst_segment_set_newsegment_full:
+ * @segment: a #GstSegment structure.
+ * @update: flag indicating a new segment is started or updated
+ * @rate: the rate of the segment.
+ * @applied_rate: the applied rate of the segment.
+ * @format: the format of the segment.
+ * @start: the new start value
+ * @stop: the new stop value
+ * @time: the new stream time
+ *
+ * Update the segment structure with the field values of a new segment event.
+ */
+void
+gst_segment_set_newsegment_full (GstSegment * segment, gboolean update,
+ gdouble rate, gdouble applied_rate, GstFormat format, gint64 start,
+ gint64 stop, gint64 time)
+{
gint64 duration;
g_return_if_fail (rate != 0.0);
+ g_return_if_fail (applied_rate != 0.0);
g_return_if_fail (segment != NULL);
if (segment->format == GST_FORMAT_UNDEFINED)
* segment. the accumulated time is used when syncing to the
* clock.
*/
- if (GST_CLOCK_TIME_IS_VALID (segment->stop)) {
+ if (segment->stop != -1) {
duration = segment->stop - segment->start;
- } else if (GST_CLOCK_TIME_IS_VALID (segment->last_stop)) {
+ } else if (segment->last_stop != -1) {
/* else use last seen timestamp as segment stop */
duration = segment->last_stop - segment->start;
} else {
- /* else we don't know */
+ /* else we don't know and throw a warning.. really, this should
+ * be fixed in the element. */
+ g_warning ("closing segment of unknown duration, assuming duration of 0");
duration = 0;
}
}
/* use previous rate to calculate duration */
- segment->accum += gst_gdouble_to_guint64 (
- (gst_guint64_to_gdouble (duration) / segment->abs_rate));
+ if (segment->abs_rate != 1.0)
+ duration /= segment->abs_rate;
+
+ /* accumulate duration */
+ segment->accum += duration;
/* then update the current segment */
segment->rate = rate;
segment->abs_rate = ABS (rate);
+ segment->applied_rate = applied_rate;
segment->start = start;
segment->last_stop = start;
segment->stop = stop;
*
* This function is typically used by elements that need to operate on
* the stream time of the buffers it receives, such as effect plugins.
- * In those use cases, @position is typically the buffer timestamp that
- * one wants to convert to the stream time.
+ * In those use cases, @position is typically the buffer timestamp or
+ * clock time that one wants to convert to the stream time.
* The stream time is always between 0 and the total duration of the
* media stream.
*
gst_segment_to_stream_time (GstSegment * segment, GstFormat format,
gint64 position)
{
- gint64 result, time;
+ gint64 result;
+ gdouble abs_applied_rate;
g_return_val_if_fail (segment != NULL, -1);
+ /* format does not matter for -1 */
+ if (position == -1)
+ return -1;
+
if (segment->format == GST_FORMAT_UNDEFINED)
segment->format = format;
else
g_return_val_if_fail (segment->format == format, -1);
- if ((time = segment->time) == -1)
- time = 0;
+ /* outside of the segment boundary stop */
+ if (segment->stop != -1 && position >= segment->stop)
+ return -1;
- if (position != -1 && position >= segment->start)
- result = ((position - segment->start) / segment->abs_rate) + time;
- else
- result = -1;
+ /* before the segment boundary */
+ if (position < segment->start)
+ return -1;
+
+ /* time must be known */
+ if (segment->time == -1)
+ return -1;
+
+ /* bring to uncorrected position in segment */
+ result = position - segment->start;
+
+ abs_applied_rate = ABS (segment->applied_rate);
+
+ /* correct for applied rate if needed */
+ if (abs_applied_rate != 1.0)
+ result *= abs_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;
+ } else {
+ /* correct for segment time, clamp at 0 */
+ if (segment->time > result)
+ result = segment->time - result;
+ else
+ result = 0;
+ }
return result;
}
* @position: the position in the segment
*
* Translate @position to the total running time using the currently configured
- * and previously accumulated segments.
+ * and previously accumulated segments. Position is a value between @segment
+ * start and stop time.
*
* This function is typically used by elements that need to synchronize to the
* global clock in a pipeline. The runnning time is a constantly increasing value
* starting from 0. When gst_segment_init() is called, this value will reset to
* 0.
*
- * Returns: the position as the total running time.
+ * This function returns -1 if the position is outside of @segment start and stop.
+ *
+ * Returns: the position as the total running time or -1 when an invalid position
+ * was given.
*/
gint64
gst_segment_to_running_time (GstSegment * segment, GstFormat format,
g_return_val_if_fail (segment != NULL, -1);
+ if (position == -1)
+ return -1;
+
if (segment->format == GST_FORMAT_UNDEFINED)
segment->format = format;
else if (segment->accum)
g_return_val_if_fail (segment->format == format, -1);
- if (position != -1 && position >= segment->start)
- result = ((position - segment->start) / segment->abs_rate) + segment->accum;
- else
- result = -1;
+ /* before the segment boundary */
+ if (position < segment->start)
+ return -1;
+
+ if (segment->rate > 0.0) {
+ /* outside of the segment boundary stop */
+ if (segment->stop != -1 && position >= segment->stop)
+ return -1;
+
+ /* bring to uncorrected position in segment */
+ result = position - segment->start;
+ } else {
+ /* cannot continue if no stop position set or outside of
+ * the segment. */
+ if (segment->stop == -1 || position >= segment->stop)
+ return -1;
+
+ /* bring to uncorrected position in segment */
+ result = segment->stop - position;
+ }
+
+ /* scale based on the rate, avoid division by and conversion to
+ * float when not needed */
+ if (segment->abs_rate != 1.0)
+ result /= segment->abs_rate;
+
+ /* correct for accumulated segments */
+ result += segment->accum;
return result;
}
* @clip_stop: the clipped stop position in the segment
*
* Clip the given @start and @stop values to the segment boundaries given
- * in @segment.
+ * in @segment. @start and @stop are compared and clipped to @segment
+ * start and stop values.
*
* If the function returns FALSE, @start and @stop are known to fall
* outside of @segment and @clip_start and @clip_stop are not updated.
res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 0, 50, &cstart, &cstop);
fail_unless (res == FALSE);
- /* touching lower bound */
+ /* touching lower bound, still outside of the segment */
res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, 100, &cstart, &cstop);
fail_unless (res == FALSE);
res = gst_segment_clip (&segment, GST_FORMAT_BYTES, -1, 100, &cstart, &cstop);
fail_unless (res == FALSE);
- /* start outside */
+ /* start outside, we don't know the stop */
res = gst_segment_clip (&segment, GST_FORMAT_BYTES, 50, -1, &cstart, &cstop);
fail_unless (res == TRUE);
fail_unless (cstart == 100);
fail_unless (segment.stop == 300);
/* add 100 to start (to 300), set stop to 200, this is not allowed.
- * nothing should be updated in the segment. */
+ * nothing should be updated in the segment. A g_warning is
+ * emited. */
ASSERT_CRITICAL (gst_segment_set_seek (&segment, 1.0,
GST_FORMAT_BYTES,
GST_SEEK_FLAG_NONE,
fail_unless (segment.time == 100);
fail_unless (segment.accum == 100);
- /* last_stop unknown, accum does not change */
+ /* last_stop 0, accum does not change */
gst_segment_set_newsegment (&segment, FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0);
fail_unless (segment.start == 0);
GST_END_TEST;
+/* mess with the segment structure in the time format */
+GST_START_TEST (segment_newsegment_streamtime)
+{
+ GstSegment segment;
+ gint64 result;
+
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+
+ /***************************
+ * Normal 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_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
+ fail_unless (result == 0);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 100);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
+ fail_unless (result == -1);
+
+ /*********************
+ * time shifted by 500
+ *********************/
+ gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
+ GST_FORMAT_TIME, 0, 200, 500);
+
+ fail_unless (segment.accum == 200);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
+ fail_unless (result == 500);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 600);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 500);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
+ fail_unless (result == -1);
+
+ /*********************
+ * time offset by 500
+ *********************/
+ gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
+ GST_FORMAT_TIME, 500, 700, 0);
+
+ fail_unless (segment.accum == 400);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ /* before segment is invalid */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 400);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 500);
+ fail_unless (result == 0);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 600);
+ fail_unless (result == 100);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 700);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 800);
+ fail_unless (result == -1);
+
+ /*************************************
+ * time offset by 500, shifted by 200
+ *************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 1.0,
+ GST_FORMAT_TIME, 500, 700, 200);
+
+ fail_unless (segment.accum == 600);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ /* before segment is invalid */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 400);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 500);
+ fail_unless (result == 200);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 600);
+ fail_unless (result == 300);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 700);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 800);
+ fail_unless (result == -1);
+}
+
+GST_END_TEST;
+
+/* mess with the segment structure in the time format */
+GST_START_TEST (segment_newsegment_streamtime_rate)
+{
+ GstSegment segment;
+ gint64 result;
+
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+
+ /***************************
+ * Normal segment rate 2.0
+ ***************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, 2.0, 1.0,
+ GST_FORMAT_TIME, 0, 200, 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 == 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_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
+ fail_unless (result == 0);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 100);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
+ fail_unless (result == 150);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
+ fail_unless (result == -1);
+
+ /***************************************
+ * Normal segment rate 2.0, offset
+ ***************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, 2.0, 1.0,
+ GST_FORMAT_TIME, 100, 300, 0);
+
+ fail_unless (segment.accum == 100);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 0);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == 100);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 250);
+ fail_unless (result == 150);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 400);
+ fail_unless (result == -1);
+
+ /***************************************
+ * Normal segment rate -1.0, offset
+ ***************************************/
+
+ /* buffers will arrive from 300 to 100 in a sink, stream time
+ * calculation is unaffected by the rate */
+ gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 1.0,
+ GST_FORMAT_TIME, 100, 300, 0);
+
+ fail_unless (segment.accum == 200);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 0);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == 100);
+
+ /***********************************************
+ * Normal segment rate -1.0, offset, time = 200
+ ***********************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 1.0,
+ GST_FORMAT_TIME, 100, 300, 200);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 200);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == 300);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 400);
+ fail_unless (result == -1);
+}
+
+GST_END_TEST;
+
+/* mess with the segment structure in the time format */
+GST_START_TEST (segment_newsegment_streamtime_applied_rate)
+{
+ GstSegment segment;
+ gint64 result;
+
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+
+ /***********************************************************
+ * Normal segment rate 1.0, applied rate -1.0
+ * This means the timestamps represents a stream going backwards
+ * starting from @time to 0.
+ ************************************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, 1.0, -1.0,
+ GST_FORMAT_TIME, 0, 200, 200);
+
+ 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 == 200);
+ 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_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ /* we count backwards from 200 */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
+ fail_unless (result == 200);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 100);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
+ fail_unless (result == 50);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
+ fail_unless (result == -1);
+
+ /***********************************************************
+ * Normal segment rate 1.0, applied rate 2.0
+ * This means the timestamps represents a stream at twice the
+ * normal rate
+ ************************************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 2.0,
+ GST_FORMAT_TIME, 0, 200, 0);
+
+ fail_unless (segment.rate == 1.0);
+ fail_unless (segment.applied_rate == 2.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 == 200);
+ fail_unless (segment.last_stop == 0);
+ fail_unless (segment.duration == -1);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
+ fail_unless (result == 0);
+
+ /* the stream prepresents a stream going twice as fast, the position
+ * in the segment is therefore scaled by the applied rate */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 200);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
+ fail_unless (result == 300);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
+ fail_unless (result == -1);
+
+ /***********************************************************
+ * Normal segment rate 1.0, applied rate -2.0
+ * This means the timestamps represents a stream at twice the
+ * reverse rate
+ ************************************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, 1.0, -2.0,
+ GST_FORMAT_TIME, 0, 200, 400);
+
+ fail_unless (segment.rate == 1.0);
+ fail_unless (segment.applied_rate == -2.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 == 400);
+ /* previous segment lasted 200, rate of 2.0 was already applied */
+ fail_unless (segment.accum == 400);
+ fail_unless (segment.last_stop == 0);
+ fail_unless (segment.duration == -1);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ /* we count backwards from 400 */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
+ fail_unless (result == 400);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 200);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
+ fail_unless (result == 100);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
+ fail_unless (result == -1);
+
+ /***********************************************************
+ * Normal segment rate 1.0, applied rate -2.0
+ * This means the timestamps represents a stream at twice the
+ * reverse rate, start time cannot compensate the complete
+ * duration of the segment so we stop at 0
+ ************************************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, 1.0, -2.0,
+ GST_FORMAT_TIME, 0, 200, 200);
+
+ fail_unless (segment.rate == 1.0);
+ fail_unless (segment.applied_rate == -2.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 == 200);
+ fail_unless (segment.accum == 600);
+ fail_unless (segment.last_stop == 0);
+ fail_unless (segment.duration == -1);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ /* we count backwards from 200 */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
+ fail_unless (result == 200);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 0);
+
+ /* clamp at 0 */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
+ fail_unless (result == 0);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
+ fail_unless (result == -1);
+}
+
+GST_END_TEST;
+
+/* mess with the segment structure in the time format */
+GST_START_TEST (segment_newsegment_streamtime_applied_rate_rate)
+{
+ GstSegment segment;
+ gint64 result;
+
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+
+ /***********************************************************
+ * Segment rate 2.0, applied rate 2.0
+ * this means we have a double speed stream that we should
+ * speed up by a factor of 2.0 some more. the resulting
+ * stream will be played at four times the speed.
+ ************************************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, 2.0, 2.0,
+ GST_FORMAT_TIME, 0, 200, 0);
+
+ fail_unless (segment.rate == 2.0);
+ fail_unless (segment.applied_rate == 2.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_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ /* only applied rate affects our calculation of the stream time */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
+ fail_unless (result == 0);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 200);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
+ fail_unless (result == 300);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
+ fail_unless (result == -1);
+
+ /***********************************************************
+ * Segment rate 2.0, applied rate -1.0
+ * this means we have a reverse stream that we should
+ * speed up by a factor of 2.0
+ ************************************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, 2.0, -1.0,
+ GST_FORMAT_TIME, 0, 200, 200);
+
+ 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 == 200);
+ fail_unless (segment.time == 200);
+ /* previous segment lasted 100 */
+ fail_unless (segment.accum == 100);
+ fail_unless (segment.last_stop == 0);
+ fail_unless (segment.duration == -1);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ /* only applied rate affects our calculation of the stream time */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
+ fail_unless (result == 200);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 100);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
+ fail_unless (result == 50);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
+ fail_unless (result == -1);
+
+ /***********************************************************
+ * Segment rate -1.0, applied rate -1.0
+ * this means we have a reverse stream that we should
+ * reverse to get the normal stream again.
+ ************************************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, -1.0, -1.0,
+ GST_FORMAT_TIME, 0, 200, 200);
+
+ 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 == 200);
+ /* accumulated 100 of previous segment to make 200 */
+ fail_unless (segment.accum == 200);
+ fail_unless (segment.last_stop == 0);
+ fail_unless (segment.duration == -1);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ /* only applied rate affects our calculation of the stream time */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
+ fail_unless (result == 200);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 100);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
+ fail_unless (result == 50);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
+ fail_unless (result == -1);
+
+ /***********************************************************
+ * Segment rate -1.0, applied rate -1.0
+ * this means we have a reverse stream that we should
+ * reverse to get the normal stream again.
+ ************************************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 2.0,
+ GST_FORMAT_TIME, 0, 200, 0);
+
+ fail_unless (segment.rate == -1.0);
+ fail_unless (segment.applied_rate == 2.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 == 400);
+ fail_unless (segment.last_stop == 0);
+ fail_unless (segment.duration == -1);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ /* only applied rate affects our calculation of the stream time */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 0);
+ fail_unless (result == 0);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 200);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 150);
+ fail_unless (result == 300);
+
+ /* outside of the segment */
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_stream_time (&segment, GST_FORMAT_TIME, 300);
+ fail_unless (result == -1);
+}
+
+GST_END_TEST;
+
+/* mess with the segment structure in the time format */
+GST_START_TEST (segment_newsegment_runningtime)
+{
+ GstSegment segment;
+ gint64 result;
+
+ gst_segment_init (&segment, GST_FORMAT_TIME);
+
+ /***************************
+ * Normal 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, 0);
+ fail_unless (result == 0);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 100);
+
+ /* outside of the segment */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 200);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 300);
+ fail_unless (result == -1);
+
+ /***********************************************************
+ * time shifted by 500, check if accumulation worked.
+ * Rate convert to twice the speed which means scaling down
+ * all positions by 2.0 in this segment.
+ * Then time argument is not used at all here.
+ ***********************************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, 2.0, 1.0,
+ GST_FORMAT_TIME, 0, 200, 500);
+
+ /* normal speed gives elapsed of 200 */
+ fail_unless (segment.accum == 200);
+
+ /* 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, 0);
+ fail_unless (result == 200);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 100);
+ fail_unless (result == 250);
+
+ /* outside of the segment */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500);
+ fail_unless (result == -1);
+
+ /********************************************
+ * time offset by 500
+ * applied rate is not used for running time
+ ********************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, 1.0, 2.0,
+ GST_FORMAT_TIME, 500, 700, 0);
+
+ /* previous segment played at double speed gives elapsed time of
+ * 100 added to previous accum of 200 gives 300. */
+ fail_unless (segment.accum == 300);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ /* before segment is invalid */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 400);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500);
+ fail_unless (result == 300);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 600);
+ fail_unless (result == 400);
+
+ /* outside of the segment */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 700);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 800);
+ fail_unless (result == -1);
+
+ /**********************************************************
+ * time offset by 500, shifted by 200
+ * Negative rate makes the running time go backwards
+ * relative to the segment stop position. again time
+ * is ignored.
+ **********************************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, -1.0, 1.0,
+ GST_FORMAT_TIME, 500, 700, 200);
+
+ fail_unless (segment.accum == 500);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ /* before segment is invalid */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 400);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500);
+ fail_unless (result == 700);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 600);
+ fail_unless (result == 600);
+
+ /* outside of the segment */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 700);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 800);
+ fail_unless (result == -1);
+
+ /**********************************************************
+ * time offset by 500, shifted by 200
+ * Negative rate makes the running time go backwards at
+ * twice speed relative to the segment stop position. again
+ * time is ignored.
+ **********************************************************/
+ gst_segment_set_newsegment_full (&segment, FALSE, -2.0, -2.0,
+ GST_FORMAT_TIME, 500, 700, 200);
+
+ fail_unless (segment.accum == 700);
+
+ /* invalid time gives invalid result */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, -1);
+ fail_unless (result == -1);
+
+ /* before segment is invalid */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 400);
+ fail_unless (result == -1);
+
+ /* total scaled segment time is 100, accum is 700, so we get 800 */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 500);
+ fail_unless (result == 800);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 600);
+ fail_unless (result == 750);
+
+ /* outside of the segment */
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 700);
+ fail_unless (result == -1);
+
+ result = gst_segment_to_running_time (&segment, GST_FORMAT_TIME, 800);
+ fail_unless (result == -1);
+
+ /* see if negative rate closed segment correctly */
+ gst_segment_set_newsegment_full (&segment, FALSE, -2.0, -1.0,
+ GST_FORMAT_TIME, 500, 700, 200);
+
+ /* previous segment lasted 100, and was at 700 so we should get 800 */
+ fail_unless (segment.accum == 800);
+}
+
+GST_END_TEST;
+
Suite *
gstsegments_suite (void)
{
tcase_add_test (tc_chain, segment_seek_size);
tcase_add_test (tc_chain, segment_newsegment_open);
tcase_add_test (tc_chain, segment_newsegment_closed);
+ tcase_add_test (tc_chain, segment_newsegment_streamtime);
+ tcase_add_test (tc_chain, segment_newsegment_streamtime_rate);
+ 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);
+
return s;
}