mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-09 08:55:33 +00:00
segment: Add _full variants of all stream/running_time from/to segment position functions
See formula clarifications in design docs for calculation details. https://bugzilla.gnome.org/show_bug.cgi?id=756564
This commit is contained in:
parent
8fc4794bcc
commit
6ff8fdfc47
6 changed files with 485 additions and 108 deletions
|
@ -101,8 +101,13 @@ The following transformation to running_time exist:
|
||||||
|
|
||||||
if (S.rate > 0.0)
|
if (S.rate > 0.0)
|
||||||
B.running_time = (B.timestamp - (S.start + S.offset)) / ABS (S.rate) + S.base
|
B.running_time = (B.timestamp - (S.start + S.offset)) / ABS (S.rate) + S.base
|
||||||
|
=>
|
||||||
|
B.timestamp = (B.running_time - S.base) * ABS (S.rate) + S.start + S.offset
|
||||||
else
|
else
|
||||||
B.running_time = ((S.stop - S.offset) - B.timestamp) / ABS (S.rate) + S.base
|
B.running_time = ((S.stop - S.offset) - B.timestamp) / ABS (S.rate) + S.base
|
||||||
|
=>
|
||||||
|
B.timestamp = S.stop - S.offset - ((B.running_time - S.base) * ABS (S.rate))
|
||||||
|
|
||||||
|
|
||||||
We write B.running_time as the running_time obtained from the SEGMENT event
|
We write B.running_time as the running_time obtained from the SEGMENT event
|
||||||
and the buffers of that segment.
|
and the buffers of that segment.
|
||||||
|
@ -191,9 +196,13 @@ Stream time is calculated using the buffer times and the preceding SEGMENT
|
||||||
event as follows:
|
event as follows:
|
||||||
|
|
||||||
stream_time = (B.timestamp - S.start) * ABS (S.applied_rate) + S.time
|
stream_time = (B.timestamp - S.start) * ABS (S.applied_rate) + S.time
|
||||||
|
=> B.timestamp = (stream_time - S.time) / ABS(S.applied_rate) + S.start
|
||||||
|
|
||||||
For negative rates, B.timestamp will go backwards from S.stop to S.start,
|
For negative rates, B.timestamp will go backwards from S.stop to S.start,
|
||||||
making the stream time go backwards.
|
making the stream time go backwards:
|
||||||
|
|
||||||
|
stream_time = (S.stop - B.timestamp) * ABS(S.applied_rate) + S.time
|
||||||
|
=> B.timestamp = S.stop - (stream_time - S.time) / ABS(S.applied_rate)
|
||||||
|
|
||||||
In the PLAYING state, it is also possible to use the pipeline clock to derive
|
In the PLAYING state, it is also possible to use the pipeline clock to derive
|
||||||
the current stream_time.
|
the current stream_time.
|
||||||
|
|
|
@ -2569,10 +2569,13 @@ gst_segment_copy
|
||||||
gst_segment_free
|
gst_segment_free
|
||||||
gst_segment_do_seek
|
gst_segment_do_seek
|
||||||
gst_segment_position_from_stream_time
|
gst_segment_position_from_stream_time
|
||||||
|
gst_segment_position_from_stream_time_full
|
||||||
gst_segment_to_running_time
|
gst_segment_to_running_time
|
||||||
gst_segment_to_running_time_full
|
gst_segment_to_running_time_full
|
||||||
gst_segment_to_stream_time
|
gst_segment_to_stream_time
|
||||||
|
gst_segment_to_stream_time_full
|
||||||
gst_segment_position_from_running_time
|
gst_segment_position_from_running_time
|
||||||
|
gst_segment_position_from_running_time_full
|
||||||
gst_segment_to_position
|
gst_segment_to_position
|
||||||
gst_segment_set_running_time
|
gst_segment_set_running_time
|
||||||
gst_segment_copy_into
|
gst_segment_copy_into
|
||||||
|
|
460
gst/gstsegment.c
460
gst/gstsegment.c
|
@ -374,6 +374,114 @@ gst_segment_do_seek (GstSegment * segment, gdouble rate,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_segment_to_stream_time_full:
|
||||||
|
* @segment: a #GstSegment structure.
|
||||||
|
* @format: the format of the segment.
|
||||||
|
* @position: the position in the segment
|
||||||
|
* @stream_time: result stream-time
|
||||||
|
*
|
||||||
|
* Translate @position to the total stream time using the currently configured
|
||||||
|
* segment. Compared to gst_segment_to_stream_time() this function can return
|
||||||
|
* negative stream-time.
|
||||||
|
*
|
||||||
|
* This function is typically used by elements that need to synchronize buffers
|
||||||
|
* against the clock or eachother.
|
||||||
|
*
|
||||||
|
* @position can be any value and the result of this function for values outside
|
||||||
|
* of the segment is extrapolated.
|
||||||
|
*
|
||||||
|
* When 1 is returned, @position resulted in a positive stream-time returned
|
||||||
|
* in @stream_time.
|
||||||
|
*
|
||||||
|
* When this function returns -1, the returned @stream_time should be negated
|
||||||
|
* to get the real negative stream time.
|
||||||
|
*
|
||||||
|
* Returns: a 1 or -1 on success, 0 on failure.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
gint
|
||||||
|
gst_segment_to_stream_time_full (const GstSegment * segment, GstFormat format,
|
||||||
|
guint64 position, guint64 * stream_time)
|
||||||
|
{
|
||||||
|
guint64 start, stop, time;
|
||||||
|
gdouble abs_applied_rate;
|
||||||
|
gint res;
|
||||||
|
|
||||||
|
/* format does not matter for -1 */
|
||||||
|
if (G_UNLIKELY (position == -1)) {
|
||||||
|
*stream_time = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_fail (segment != NULL, 0);
|
||||||
|
g_return_val_if_fail (segment->format == format, 0);
|
||||||
|
|
||||||
|
stop = segment->stop;
|
||||||
|
|
||||||
|
start = segment->start;
|
||||||
|
time = segment->time;
|
||||||
|
|
||||||
|
/* time must be known */
|
||||||
|
if (G_UNLIKELY (time == -1))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
abs_applied_rate = ABS (segment->applied_rate);
|
||||||
|
|
||||||
|
/* add or subtract from segment time based on applied rate */
|
||||||
|
if (G_LIKELY (segment->applied_rate > 0.0)) {
|
||||||
|
if (G_LIKELY (position > start)) {
|
||||||
|
/* bring to uncorrected position in segment */
|
||||||
|
*stream_time = position - start;
|
||||||
|
/* correct for applied rate if needed */
|
||||||
|
if (G_UNLIKELY (abs_applied_rate != 1.0))
|
||||||
|
*stream_time *= abs_applied_rate;
|
||||||
|
/* correct for segment time */
|
||||||
|
*stream_time += time;
|
||||||
|
res = 1;
|
||||||
|
} else {
|
||||||
|
*stream_time = start - position;
|
||||||
|
if (G_UNLIKELY (abs_applied_rate != 1.0))
|
||||||
|
*stream_time *= abs_applied_rate;
|
||||||
|
if (*stream_time > time) {
|
||||||
|
*stream_time -= time;
|
||||||
|
res = -1;
|
||||||
|
} else {
|
||||||
|
*stream_time = time - *stream_time;
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* correct for segment time. Streams with a negative applied_rate
|
||||||
|
* have timestamps between start and stop, as usual, but have the
|
||||||
|
* time member starting high and going backwards. */
|
||||||
|
/* cannot continue without a known segment stop */
|
||||||
|
if (G_UNLIKELY (stop == -1))
|
||||||
|
return 0;
|
||||||
|
if (G_UNLIKELY (position > stop)) {
|
||||||
|
*stream_time = position - stop;
|
||||||
|
if (G_UNLIKELY (abs_applied_rate != 1.0))
|
||||||
|
*stream_time *= abs_applied_rate;
|
||||||
|
if (*stream_time > time) {
|
||||||
|
*stream_time -= time;
|
||||||
|
res = -1;
|
||||||
|
} else {
|
||||||
|
*stream_time = time - *stream_time;
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*stream_time = stop - position;
|
||||||
|
if (G_UNLIKELY (abs_applied_rate != 1.0))
|
||||||
|
*stream_time *= abs_applied_rate;
|
||||||
|
*stream_time += time;
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_segment_to_stream_time:
|
* gst_segment_to_stream_time:
|
||||||
* @segment: a #GstSegment structure.
|
* @segment: a #GstSegment structure.
|
||||||
|
@ -393,65 +501,146 @@ gst_segment_do_seek (GstSegment * segment, gdouble rate,
|
||||||
*
|
*
|
||||||
* Returns: the position in stream_time or -1 when an invalid position
|
* Returns: the position in stream_time or -1 when an invalid position
|
||||||
* was given.
|
* was given.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
*/
|
*/
|
||||||
guint64
|
guint64
|
||||||
gst_segment_to_stream_time (const GstSegment * segment, GstFormat format,
|
gst_segment_to_stream_time (const GstSegment * segment, GstFormat format,
|
||||||
guint64 position)
|
guint64 position)
|
||||||
{
|
{
|
||||||
guint64 stream_time, start, stop, time;
|
guint64 result;
|
||||||
gdouble abs_applied_rate;
|
|
||||||
|
|
||||||
/* format does not matter for -1 */
|
|
||||||
if (G_UNLIKELY (position == -1))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
g_return_val_if_fail (segment != NULL, -1);
|
g_return_val_if_fail (segment != NULL, -1);
|
||||||
g_return_val_if_fail (segment->format == format, -1);
|
g_return_val_if_fail (segment->format == format, -1);
|
||||||
|
|
||||||
stop = segment->stop;
|
/* before the segment boundary */
|
||||||
|
if (G_UNLIKELY (position < segment->start)) {
|
||||||
/* outside of the segment boundary stop */
|
GST_DEBUG ("position(%" G_GUINT64_FORMAT ") < start(%" G_GUINT64_FORMAT
|
||||||
if (G_UNLIKELY (stop != -1 && position > stop))
|
")", position, segment->start);
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
/* after the segment boundary */
|
||||||
|
if (G_UNLIKELY (segment->stop != -1 && position > segment->stop)) {
|
||||||
|
GST_DEBUG ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT
|
||||||
|
")", position, segment->stop);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gst_segment_to_stream_time_full (segment, format, position, &result) == 1)
|
||||||
|
return result;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_segment_position_from_stream_time_full:
|
||||||
|
* @segment: a #GstSegment structure.
|
||||||
|
* @format: the format of the segment.
|
||||||
|
* @stream_time: the stream-time
|
||||||
|
* @position: the resulting position in the segment
|
||||||
|
*
|
||||||
|
* Translate @stream_time to the segment position using the currently configured
|
||||||
|
* segment. Compared to gst_segment_position_from_stream_time() this function can
|
||||||
|
* return negative segment position.
|
||||||
|
*
|
||||||
|
* This function is typically used by elements that need to synchronize buffers
|
||||||
|
* against the clock or each other.
|
||||||
|
*
|
||||||
|
* @stream_time can be any value and the result of this function for values outside
|
||||||
|
* of the segment is extrapolated.
|
||||||
|
*
|
||||||
|
* When 1 is returned, @stream_time resulted in a positive position returned
|
||||||
|
* in @position.
|
||||||
|
*
|
||||||
|
* When this function returns -1, the returned @position should be negated
|
||||||
|
* to get the real negative segment position.
|
||||||
|
*
|
||||||
|
* Returns: a 1 or -1 on success, 0 on failure.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
gint
|
||||||
|
gst_segment_position_from_stream_time_full (const GstSegment * segment,
|
||||||
|
GstFormat format, guint64 stream_time, guint64 * position)
|
||||||
|
{
|
||||||
|
guint64 start, time;
|
||||||
|
gdouble abs_applied_rate;
|
||||||
|
gint res;
|
||||||
|
|
||||||
|
/* format does not matter for -1 */
|
||||||
|
if (G_UNLIKELY (stream_time == -1)) {
|
||||||
|
*position = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_return_val_if_fail (segment != NULL, -1);
|
||||||
|
g_return_val_if_fail (segment->format == format, -1);
|
||||||
|
|
||||||
start = segment->start;
|
start = segment->start;
|
||||||
|
|
||||||
/* before the segment boundary */
|
|
||||||
if (G_UNLIKELY (position < start))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
time = segment->time;
|
time = segment->time;
|
||||||
|
|
||||||
/* time must be known */
|
/* time must be known */
|
||||||
if (G_UNLIKELY (time == -1))
|
if (G_UNLIKELY (time == -1))
|
||||||
return -1;
|
return 0;
|
||||||
|
|
||||||
abs_applied_rate = ABS (segment->applied_rate);
|
abs_applied_rate = ABS (segment->applied_rate);
|
||||||
|
|
||||||
/* add or subtract from segment time based on applied rate */
|
|
||||||
if (G_LIKELY (segment->applied_rate > 0.0)) {
|
if (G_LIKELY (segment->applied_rate > 0.0)) {
|
||||||
if (G_UNLIKELY (position < start))
|
if (G_LIKELY (stream_time > time)) {
|
||||||
return -1;
|
res = 1;
|
||||||
/* bring to uncorrected position in segment */
|
*position = stream_time - time;
|
||||||
stream_time = position - start;
|
} else {
|
||||||
|
res = -1;
|
||||||
|
*position = time - stream_time;
|
||||||
|
}
|
||||||
/* correct for applied rate if needed */
|
/* correct for applied rate if needed */
|
||||||
if (G_UNLIKELY (abs_applied_rate != 1.0))
|
if (G_UNLIKELY (abs_applied_rate != 1.0))
|
||||||
stream_time *= abs_applied_rate;
|
*position /= abs_applied_rate;
|
||||||
/* correct for segment time */
|
|
||||||
stream_time += time;
|
if (G_UNLIKELY (res == -1)) {
|
||||||
|
if (*position > start) {
|
||||||
|
*position -= start;
|
||||||
} else {
|
} else {
|
||||||
/* correct for segment time, clamp at 0. Streams with a negative
|
*position = start - *position;
|
||||||
* applied_rate have timestamps between start and stop, as usual, but have
|
res = 1;
|
||||||
* the time member starting high and going backwards. */
|
}
|
||||||
if (G_UNLIKELY (position > stop))
|
} else {
|
||||||
return -1;
|
*position += start;
|
||||||
stream_time = stop - position;
|
}
|
||||||
|
} else {
|
||||||
|
GstClockTime stop = segment->stop;
|
||||||
|
/* cannot continue without a known segment stop */
|
||||||
|
if (G_UNLIKELY (stop == -1))
|
||||||
|
return 0;
|
||||||
|
if (G_UNLIKELY (time > stream_time)) {
|
||||||
|
res = -1;
|
||||||
|
*position = time - stream_time;
|
||||||
|
} else {
|
||||||
|
res = 1;
|
||||||
|
*position = stream_time - time;
|
||||||
|
}
|
||||||
if (G_UNLIKELY (abs_applied_rate != 1.0))
|
if (G_UNLIKELY (abs_applied_rate != 1.0))
|
||||||
stream_time *= abs_applied_rate;
|
*position /= abs_applied_rate;
|
||||||
stream_time += time;
|
if (G_UNLIKELY (stop < *position)) {
|
||||||
|
if (G_LIKELY (res == 1)) {
|
||||||
|
*position -= stop;
|
||||||
|
res = -1;
|
||||||
|
} else {
|
||||||
|
*position += stop;
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (G_LIKELY (res == 1)) {
|
||||||
|
*position = stop - *position;
|
||||||
|
res = 1;
|
||||||
|
} else {
|
||||||
|
*position += stop;
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return stream_time;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -472,56 +661,34 @@ guint64
|
||||||
gst_segment_position_from_stream_time (const GstSegment * segment,
|
gst_segment_position_from_stream_time (const GstSegment * segment,
|
||||||
GstFormat format, guint64 stream_time)
|
GstFormat format, guint64 stream_time)
|
||||||
{
|
{
|
||||||
guint64 position, start, stop, time;
|
guint64 position;
|
||||||
gdouble abs_applied_rate;
|
gint res;
|
||||||
|
|
||||||
/* format does not matter for -1 */
|
|
||||||
if (G_UNLIKELY (stream_time == -1))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
g_return_val_if_fail (segment != NULL, -1);
|
g_return_val_if_fail (segment != NULL, -1);
|
||||||
g_return_val_if_fail (segment->format == format, -1);
|
g_return_val_if_fail (segment->format == format, -1);
|
||||||
|
|
||||||
start = segment->start;
|
res =
|
||||||
time = segment->time;
|
gst_segment_position_from_stream_time_full (segment, format, stream_time,
|
||||||
/* this stream time was for a previous segment */
|
&position);
|
||||||
if (G_UNLIKELY (stream_time < segment->time))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* time must be known */
|
/* before the segment boundary */
|
||||||
if (G_UNLIKELY (time == -1))
|
if (G_UNLIKELY (position < segment->start)) {
|
||||||
return -1;
|
GST_DEBUG ("position(%" G_GUINT64_FORMAT ") < start(%" G_GUINT64_FORMAT
|
||||||
|
")", position, segment->start);
|
||||||
position = stream_time - time;
|
|
||||||
|
|
||||||
abs_applied_rate = ABS (segment->applied_rate);
|
|
||||||
stop = segment->stop;
|
|
||||||
|
|
||||||
/* correct for applied rate if needed */
|
|
||||||
if (G_UNLIKELY (abs_applied_rate != 1.0))
|
|
||||||
position /= abs_applied_rate;
|
|
||||||
|
|
||||||
if (G_LIKELY (segment->applied_rate > 0.0)) {
|
|
||||||
position += start;
|
|
||||||
/* outside of the segment boundary stop */
|
|
||||||
if (G_UNLIKELY (stop != -1 && position > stop))
|
|
||||||
return -1;
|
|
||||||
} else {
|
|
||||||
/* cannot calculate without known boundary stop */
|
|
||||||
if (G_UNLIKELY (stop == -1))
|
|
||||||
return -1;
|
|
||||||
/* outside segment boundary */
|
|
||||||
if (G_UNLIKELY (position > stop))
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
position = stop - position;
|
|
||||||
|
|
||||||
/* position before segment start */
|
|
||||||
if (G_UNLIKELY (position < start))
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* after the segment boundary */
|
||||||
|
if (G_UNLIKELY (segment->stop != -1 && position > segment->stop)) {
|
||||||
|
GST_DEBUG ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT
|
||||||
|
")", position, segment->stop);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res == 1)
|
||||||
return position;
|
return position;
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -766,50 +933,139 @@ guint64
|
||||||
gst_segment_position_from_running_time (const GstSegment * segment,
|
gst_segment_position_from_running_time (const GstSegment * segment,
|
||||||
GstFormat format, guint64 running_time)
|
GstFormat format, guint64 running_time)
|
||||||
{
|
{
|
||||||
guint64 result;
|
guint64 position;
|
||||||
|
gint res;
|
||||||
|
|
||||||
|
g_return_val_if_fail (segment != NULL, -1);
|
||||||
|
g_return_val_if_fail (segment->format == format, -1);
|
||||||
|
|
||||||
|
res =
|
||||||
|
gst_segment_position_from_running_time_full (segment, format,
|
||||||
|
running_time, &position);
|
||||||
|
|
||||||
|
if (res != 1) {
|
||||||
|
g_print
|
||||||
|
("here with start %lu stop %lu base %lu rate %f offset %lu running_time %lu position %lu\n",
|
||||||
|
segment->start, segment->stop, segment->base, segment->rate,
|
||||||
|
segment->offset, running_time, position);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* before the segment boundary */
|
||||||
|
if (G_UNLIKELY (position < segment->start)) {
|
||||||
|
GST_DEBUG ("position(%" G_GUINT64_FORMAT ") < start(%" G_GUINT64_FORMAT
|
||||||
|
")", position, segment->start);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* after the segment boundary */
|
||||||
|
if (G_UNLIKELY (segment->stop != -1 && position > segment->stop)) {
|
||||||
|
GST_DEBUG ("position(%" G_GUINT64_FORMAT ") > stop(%" G_GUINT64_FORMAT
|
||||||
|
")", position, segment->stop);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_segment_position_from_running_time_full:
|
||||||
|
* @segment: a #GstSegment structure.
|
||||||
|
* @format: the format of the segment.
|
||||||
|
* @running_time: the running-time
|
||||||
|
* @position: the resulting position in the segment
|
||||||
|
*
|
||||||
|
* Translate @running_time to the segment position using the currently configured
|
||||||
|
* segment. Compared to gst_segment_position_from_running_time() this function can
|
||||||
|
* return negative segment position.
|
||||||
|
*
|
||||||
|
* This function is typically used by elements that need to synchronize buffers
|
||||||
|
* against the clock or each other.
|
||||||
|
*
|
||||||
|
* @running_time can be any value and the result of this function for values
|
||||||
|
* outside of the segment is extrapolated.
|
||||||
|
*
|
||||||
|
* When 1 is returned, @running_time resulted in a positive position returned
|
||||||
|
* in @position.
|
||||||
|
*
|
||||||
|
* When this function returns -1, the returned @position should be negated
|
||||||
|
* to get the real negative segment position.
|
||||||
|
*
|
||||||
|
* Returns: a 1 or -1 on success, 0 on failure.
|
||||||
|
*
|
||||||
|
* Since: 1.8
|
||||||
|
*/
|
||||||
|
gint
|
||||||
|
gst_segment_position_from_running_time_full (const GstSegment * segment,
|
||||||
|
GstFormat format, guint64 running_time, guint64 * position)
|
||||||
|
{
|
||||||
|
gint res;
|
||||||
guint64 start, stop, base;
|
guint64 start, stop, base;
|
||||||
gdouble abs_rate;
|
gdouble abs_rate;
|
||||||
|
|
||||||
if (G_UNLIKELY (running_time == -1))
|
if (G_UNLIKELY (running_time == -1)) {
|
||||||
return -1;
|
*position = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
g_return_val_if_fail (segment != NULL, -1);
|
g_return_val_if_fail (segment != NULL, 0);
|
||||||
g_return_val_if_fail (segment->format == format, FALSE);
|
g_return_val_if_fail (segment->format == format, 0);
|
||||||
|
|
||||||
base = segment->base;
|
base = segment->base;
|
||||||
|
|
||||||
/* this running_time was for a previous segment */
|
|
||||||
if (running_time < base)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* start by subtracting the base time */
|
|
||||||
result = running_time - base;
|
|
||||||
|
|
||||||
/* move into the segment at the right rate */
|
|
||||||
abs_rate = ABS (segment->rate);
|
abs_rate = ABS (segment->rate);
|
||||||
if (G_UNLIKELY (abs_rate != 1.0))
|
|
||||||
result = ceil (result * abs_rate);
|
|
||||||
|
|
||||||
start = segment->start;
|
start = segment->start;
|
||||||
stop = segment->stop;
|
stop = segment->stop;
|
||||||
|
|
||||||
if (G_LIKELY (segment->rate > 0.0)) {
|
if (G_LIKELY (segment->rate > 0.0)) {
|
||||||
|
/* start by subtracting the base time */
|
||||||
|
if (G_LIKELY (running_time >= base)) {
|
||||||
|
*position = running_time - base;
|
||||||
|
/* move into the segment at the right rate */
|
||||||
|
if (G_UNLIKELY (abs_rate != 1.0))
|
||||||
|
*position = ceil (*position * abs_rate);
|
||||||
/* bring to corrected position in segment */
|
/* bring to corrected position in segment */
|
||||||
result += start + segment->offset;
|
*position += start + segment->offset;
|
||||||
|
res = 1;
|
||||||
/* outside of the segment boundary stop */
|
|
||||||
if (G_UNLIKELY (stop != -1 && result > stop))
|
|
||||||
return -1;
|
|
||||||
} else {
|
} else {
|
||||||
/* cannot continue if no stop position set or outside of
|
*position = base - running_time;
|
||||||
* the segment. */
|
if (G_UNLIKELY (abs_rate != 1.0))
|
||||||
if (G_UNLIKELY (stop == -1 || result + start > stop))
|
*position = ceil (*position * abs_rate);
|
||||||
return -1;
|
if (start + segment->offset > *position) {
|
||||||
|
*position -= start + segment->offset;
|
||||||
/* bring to corrected position in segment */
|
res = -1;
|
||||||
result = stop - result - segment->offset;
|
} else {
|
||||||
|
*position = start + segment->offset - *position;
|
||||||
|
res = 1;
|
||||||
}
|
}
|
||||||
return result;
|
}
|
||||||
|
} else {
|
||||||
|
if (G_LIKELY (running_time >= base)) {
|
||||||
|
*position = running_time - base;
|
||||||
|
if (G_UNLIKELY (abs_rate != 1.0))
|
||||||
|
*position = ceil (*position * abs_rate);
|
||||||
|
if (G_UNLIKELY (stop < *position + segment->offset)) {
|
||||||
|
*position += segment->offset - stop;
|
||||||
|
res = -1;
|
||||||
|
} else {
|
||||||
|
*position = stop - *position - segment->offset;
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
*position = base - running_time;
|
||||||
|
if (G_UNLIKELY (abs_rate != 1.0))
|
||||||
|
*position = ceil (*position * abs_rate);
|
||||||
|
if (G_UNLIKELY (stop < segment->offset - *position)) {
|
||||||
|
*position -= segment->offset - stop;
|
||||||
|
res = -1;
|
||||||
|
} else {
|
||||||
|
*position = stop + *position - segment->offset;
|
||||||
|
res = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -218,7 +218,9 @@ void gst_segment_free (GstSegment *segment);
|
||||||
|
|
||||||
void gst_segment_init (GstSegment *segment, GstFormat format);
|
void gst_segment_init (GstSegment *segment, GstFormat format);
|
||||||
|
|
||||||
|
gint gst_segment_to_stream_time_full (const GstSegment *segment, GstFormat format, guint64 position, guint64 * stream_time);
|
||||||
guint64 gst_segment_to_stream_time (const GstSegment *segment, GstFormat format, guint64 position);
|
guint64 gst_segment_to_stream_time (const GstSegment *segment, GstFormat format, guint64 position);
|
||||||
|
gint gst_segment_position_from_stream_time_full (const GstSegment * segment, GstFormat format, guint64 stream_time, guint64 * position);
|
||||||
guint64 gst_segment_position_from_stream_time (const GstSegment * segment, GstFormat format, guint64 stream_time);
|
guint64 gst_segment_position_from_stream_time (const GstSegment * segment, GstFormat format, guint64 stream_time);
|
||||||
guint64 gst_segment_to_running_time (const GstSegment *segment, GstFormat format, guint64 position);
|
guint64 gst_segment_to_running_time (const GstSegment *segment, GstFormat format, guint64 position);
|
||||||
|
|
||||||
|
@ -227,6 +229,7 @@ gint gst_segment_to_running_time_full (const GstSegment *segment, GstFor
|
||||||
#ifndef GST_DISABLE_DEPRECATED
|
#ifndef GST_DISABLE_DEPRECATED
|
||||||
guint64 gst_segment_to_position (const GstSegment *segment, GstFormat format, guint64 running_time);
|
guint64 gst_segment_to_position (const GstSegment *segment, GstFormat format, guint64 running_time);
|
||||||
#endif
|
#endif
|
||||||
|
gint gst_segment_position_from_running_time_full (const GstSegment *segment, GstFormat format, guint64 running_time, guint64 * position);
|
||||||
guint64 gst_segment_position_from_running_time (const GstSegment *segment, GstFormat format, guint64 running_time);
|
guint64 gst_segment_position_from_running_time (const GstSegment *segment, GstFormat format, guint64 running_time);
|
||||||
|
|
||||||
gboolean gst_segment_set_running_time (GstSegment *segment, GstFormat format, guint64 running_time);
|
gboolean gst_segment_set_running_time (GstSegment *segment, GstFormat format, guint64 running_time);
|
||||||
|
|
|
@ -755,7 +755,7 @@ GST_END_TEST;
|
||||||
GST_START_TEST (segment_full)
|
GST_START_TEST (segment_full)
|
||||||
{
|
{
|
||||||
GstSegment segment;
|
GstSegment segment;
|
||||||
guint64 rt;
|
guint64 rt, pos;
|
||||||
|
|
||||||
gst_segment_init (&segment, GST_FORMAT_TIME);
|
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||||
|
|
||||||
|
@ -770,9 +770,15 @@ GST_START_TEST (segment_full)
|
||||||
fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
|
fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
|
||||||
50, &rt) == 1);
|
50, &rt) == 1);
|
||||||
fail_unless (rt == 0);
|
fail_unless (rt == 0);
|
||||||
|
fail_unless (gst_segment_position_from_running_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, rt, &pos) == 1);
|
||||||
|
fail_unless (pos == 50);
|
||||||
fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
|
fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME,
|
||||||
200, &rt) == 1);
|
200, &rt) == 1);
|
||||||
fail_unless (rt == 150);
|
fail_unless (rt == 150);
|
||||||
|
fail_unless (gst_segment_position_from_running_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, rt, &pos) == 1);
|
||||||
|
fail_unless (pos == 200);
|
||||||
fail_unless (!gst_segment_clip (&segment, GST_FORMAT_TIME, 40, 40, NULL,
|
fail_unless (!gst_segment_clip (&segment, GST_FORMAT_TIME, 40, 40, NULL,
|
||||||
NULL));
|
NULL));
|
||||||
fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, 40,
|
fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, 40,
|
||||||
|
@ -785,6 +791,9 @@ GST_START_TEST (segment_full)
|
||||||
NULL));
|
NULL));
|
||||||
fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, 201,
|
fail_unless (gst_segment_to_running_time_full (&segment, GST_FORMAT_TIME, 201,
|
||||||
&rt) == 1);
|
&rt) == 1);
|
||||||
|
fail_unless (gst_segment_position_from_running_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, rt, &pos) == 1);
|
||||||
|
fail_unless (pos == 201);
|
||||||
|
|
||||||
fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
|
fail_unless (gst_segment_offset_running_time (&segment, GST_FORMAT_TIME,
|
||||||
-50) == TRUE);
|
-50) == TRUE);
|
||||||
|
@ -794,6 +803,99 @@ GST_START_TEST (segment_full)
|
||||||
50, &rt) == -1);
|
50, &rt) == -1);
|
||||||
GST_DEBUG ("%" G_GUINT64_FORMAT, rt);
|
GST_DEBUG ("%" G_GUINT64_FORMAT, rt);
|
||||||
fail_unless (rt == 50);
|
fail_unless (rt == 50);
|
||||||
|
|
||||||
|
segment.start = 50;
|
||||||
|
segment.stop = 300;
|
||||||
|
segment.position = 150;
|
||||||
|
segment.time = 0;
|
||||||
|
segment.offset = 0;
|
||||||
|
gst_segment_set_running_time (&segment, GST_FORMAT_TIME, 100);
|
||||||
|
fail_unless_equals_int (segment.base, 100);
|
||||||
|
fail_unless (gst_segment_position_from_running_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, 70, &pos) == -1);
|
||||||
|
fail_unless (gst_segment_position_from_running_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, 140, &pos) == 1);
|
||||||
|
fail_unless_equals_int (pos, 190);
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_END_TEST;
|
||||||
|
|
||||||
|
GST_START_TEST (segment_stream_time_full)
|
||||||
|
{
|
||||||
|
GstSegment segment;
|
||||||
|
guint64 st, pos;
|
||||||
|
|
||||||
|
gst_segment_init (&segment, GST_FORMAT_TIME);
|
||||||
|
|
||||||
|
segment.start = 50;
|
||||||
|
segment.stop = 200;
|
||||||
|
segment.time = 30;
|
||||||
|
segment.position = 0;
|
||||||
|
|
||||||
|
fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
|
||||||
|
0, &st) == -1);
|
||||||
|
fail_unless_equals_int (st, 20);
|
||||||
|
fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
|
||||||
|
20, &st) == 1);
|
||||||
|
fail_unless_equals_int (st, 0);
|
||||||
|
fail_unless (gst_segment_position_from_stream_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, 0, &pos) == 1);
|
||||||
|
fail_unless_equals_int (pos, 20);
|
||||||
|
fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
|
||||||
|
10, &st) == -1);
|
||||||
|
fail_unless_equals_int (st, 10);
|
||||||
|
fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
|
||||||
|
40, &st) == 1);
|
||||||
|
fail_unless_equals_int (st, 20);
|
||||||
|
fail_unless (gst_segment_position_from_stream_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, st, &pos) == 1);
|
||||||
|
fail_unless_equals_int (pos, 40);
|
||||||
|
segment.time = 100;
|
||||||
|
fail_unless (gst_segment_position_from_stream_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, 40, &pos) == -1);
|
||||||
|
fail_unless_equals_int (pos, 10);
|
||||||
|
fail_unless (gst_segment_position_from_stream_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, 60, &pos) == 1);
|
||||||
|
fail_unless_equals_int (pos, 10);
|
||||||
|
|
||||||
|
segment.start = 50;
|
||||||
|
segment.position = 150;
|
||||||
|
segment.stop = 200;
|
||||||
|
segment.time = 0;
|
||||||
|
segment.applied_rate = -1;
|
||||||
|
segment.rate = -1;
|
||||||
|
|
||||||
|
fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
|
||||||
|
0, &st) == 1);
|
||||||
|
fail_unless_equals_int (st, 200);
|
||||||
|
fail_unless (gst_segment_position_from_stream_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, 200, &pos) == 1);
|
||||||
|
fail_unless_equals_int (pos, 0);
|
||||||
|
fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
|
||||||
|
250, &st) == -1);
|
||||||
|
fail_unless_equals_int (st, 50);
|
||||||
|
fail_unless (gst_segment_position_from_stream_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, 200, &pos) == 1);
|
||||||
|
fail_unless_equals_int (pos, 0);
|
||||||
|
fail_unless (gst_segment_position_from_stream_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, 250, &pos) == -1);
|
||||||
|
fail_unless_equals_int (pos, 50);
|
||||||
|
|
||||||
|
segment.time = 70;
|
||||||
|
fail_unless (gst_segment_to_stream_time_full (&segment, GST_FORMAT_TIME,
|
||||||
|
250, &st) == 1);
|
||||||
|
fail_unless_equals_int (st, 20);
|
||||||
|
fail_unless (gst_segment_position_from_stream_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, 50, &pos) == 1);
|
||||||
|
fail_unless_equals_int (pos, 220);
|
||||||
|
fail_unless (gst_segment_position_from_stream_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, 90, &pos) == 1);
|
||||||
|
fail_unless_equals_int (pos, 180);
|
||||||
|
|
||||||
|
segment.stop = 60;
|
||||||
|
fail_unless (gst_segment_position_from_stream_time_full (&segment,
|
||||||
|
GST_FORMAT_TIME, 5, &pos) == 1);
|
||||||
|
fail_unless_equals_int (pos, 125);
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_END_TEST;
|
GST_END_TEST;
|
||||||
|
@ -897,6 +999,7 @@ gst_segment_suite (void)
|
||||||
tcase_add_test (tc_chain, segment_full);
|
tcase_add_test (tc_chain, segment_full);
|
||||||
tcase_add_test (tc_chain, segment_negative_rate);
|
tcase_add_test (tc_chain, segment_negative_rate);
|
||||||
tcase_add_test (tc_chain, segment_negative_applied_rate);
|
tcase_add_test (tc_chain, segment_negative_applied_rate);
|
||||||
|
tcase_add_test (tc_chain, segment_stream_time_full);
|
||||||
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1158,12 +1158,15 @@ EXPORTS
|
||||||
gst_segment_new
|
gst_segment_new
|
||||||
gst_segment_offset_running_time
|
gst_segment_offset_running_time
|
||||||
gst_segment_position_from_running_time
|
gst_segment_position_from_running_time
|
||||||
|
gst_segment_position_from_running_time_full
|
||||||
gst_segment_position_from_stream_time
|
gst_segment_position_from_stream_time
|
||||||
|
gst_segment_position_from_stream_time_full
|
||||||
gst_segment_set_running_time
|
gst_segment_set_running_time
|
||||||
gst_segment_to_position
|
gst_segment_to_position
|
||||||
gst_segment_to_running_time
|
gst_segment_to_running_time
|
||||||
gst_segment_to_running_time_full
|
gst_segment_to_running_time_full
|
||||||
gst_segment_to_stream_time
|
gst_segment_to_stream_time
|
||||||
|
gst_segment_to_stream_time_full
|
||||||
gst_segtrap_is_enabled
|
gst_segtrap_is_enabled
|
||||||
gst_segtrap_set_enabled
|
gst_segtrap_set_enabled
|
||||||
gst_state_change_get_type
|
gst_state_change_get_type
|
||||||
|
|
Loading…
Reference in a new issue